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