数据库
首页 > 数据库> > mysql-在单个字段上可靠的de / increment所需的隔离级别

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

作者:互联网

假设我们有一个下表,

+----+---------+--------+
| 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