ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

mysql-在单个字段上可靠的de / increment所需的隔离级别

2019-12-08 20:14:55  阅读:298  来源: 互联网

标签:isolation-level concurrency atomicity transactions mysql


假设我们有一个下表,

+----+---------+--------+
| id | Name    | Bunnies|
+----+---------+--------+
|  1 | England |   1000 |
|  2 | Russia  |   1000 |
+----+---------+--------+

而且,在指定的时间段(例如2小时)内,有多个用户删除了兔子. (因此,返回了0个兔子,最多1000个兔子,返回的是兔子,用户未添加)

我正在使用两个基本的交易查询,例如

BEGIN;
  UPDATE `BunnyTracker` SET `Bunnies`=`Bunnies`+1 where `id`=1;
COMMIT;

当有人归还兔子时,

BEGIN;
  UPDATE `BunnyTracker` SET `Bunnies`=`Bunnies`-1 where `id`=1 AND `Bunnies` > 0;
COMMIT;

当某人试图采取兔子.我假设这些查询将在后台实现某种原子性

至关重要的是,用户接受的兔子不能超过每个国家/地区(例如,如果23位用户同时进行交易,则可以获得-23个兔子)

我的问题是,在这种情况下,如何保持ACID安全,同时能够同时添加/增加/减少兔子字段,同时又保持在范围内(0-1000)
我可以将隔离级别设置为序列化,但是我担心这会降低性能.

有小费吗?
提前致谢

解决方法:

我相信您需要实现一些其他逻辑,以防止并发的增量和减量事务读取相同的初始值.

就目前而言,如果Bunnies = 1,您可以同时进行增量和减量事务处理,它们都读取初始值1.如果增量先完成,则其结果将被忽略,因为减量已经读取了初始值1.并将这些值减为0.这些操作中最后一个完成的操作将有效地取消另一个操作.

要解决此问题,您需要使用SELECT … FOR UPDATE来实现锁定读取,如下所示:
描述here.例如:

BEGIN;
  SELECT `Bunnies` FROM `BunnyTracker` where `id`=1 FOR UPDATE;
  UPDATE `BunnyTracker` SET `Bunnies`=`Bunnies`+1 where `id`=1;
COMMIT;

标签:isolation-level,concurrency,atomicity,transactions,mysql
来源: https://codeday.me/bug/20191208/2094119.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有