mysql - MySql 的原子计数器
问题描述
使用 MySql 8.0,我正在处理一个“原子计数器”(在存储过程中),这个简单的解决方法(我不能使用事务)非常适合我的目的:
CREATE PROCEDURE xxx...
...
UPDATE cnt SET value = (@val := value + 1) where id = 1;
...
但是当我编译程序时,我收到了这个警告
Setting user variables within expressions is deprecated and will be removed in a future release. ...
我怎样才能避免警告信息?(我找不到“新”语法)
解决方案
无需在表达式中设置变量的模拟原子计数器可以通过
repeat
select value + 1 into @value from cnt where id = 1;
update cnt set value = @value where id = 1 and value = @value - 1;
until (select row_count()) > 0 end repeat;
这实际上不是原子的(因为不同的会话可以增加和之间的计数器select
)update
,但它只会在没有发生的情况下更新,否则它会重试(如果你有一个非常忙碌的计数器,可能会无限期地重试)。row_count()
用于检查该更新是否发生。
该不推荐使用的功能没有“新语法” - 有意地,在 MySQL 9 中不再可能执行此操作(因此警告),请参阅更改日志。在表达式中设置用户变量的主要用例是模拟 CTE(例如递归分层查询或rank()
窗口函数),并且在 MySQL 8 中 CTE 的支持下,可以弃用此功能。
对于上下文,您的语法的预期行为是使
UPDATE cnt SET value = value + 1 where id = 1;
SELECT value INTO @val from cnt where id = 1;
原子行为。
显然,实现这一点的预期方法是使用事务,因此不会有新的语法来替换您的行为,就像 CTE 所需要的那样;但是,您可能想检查您无法使用事务的原因是否可能在较新的 MySQL 版本中消失(具有潜在的新功能)。
推荐阅读
- kotlin - 在没有类的 kotlin 文件中将@since 标签放在哪里?
- javascript - javascript中的数组和数据处理
- javascript - 如何在 Safari 中从 iframe 设置 3rd 方 cookie
- python - python中函数的前向声明
- git - Bitbucket 的解决方案 -> 可以构建不同操作系统的管道 -> 部署到硬件
- java - 这个算法的时间复杂度是 O(n) 还是 O(n^2)?
- php - 谷歌图表不显示来自 MySql 数据库的结果
- flutter - Flutter 中的 pushReplacementNamed 和 popAndPushNamed 有什么区别?
- reactjs - 基于所选项目的 URL 更改 - 但页面不刷新
- javascript - 调用 document.createElement 时是否会调用 HTMLTableElement 的构造函数?