mysql 队列 实现并发读

时间:2024-01-14 21:16:26 

一个 MySQL 表可以看作是一个队列,每一行为一个元素。每次查询得到满足某个条件的最前面的一行,并将它从表中删除或者改变它的状态,使得下次查询不会得到它。在没有并发访问的情况下,简单地用 SELECT 得到一行,再用UPDATE(或者DELETE)语句修改之,就可以实现。


SELECT * FROM targets WHERE status='C' LIMIT 1;
UPDATE targets SET status='D' WHERE id='id';


如果有并发访问,在SELECT和UPDATE语句之间可能会存在其他地SELECT查询,导致同一行被取出多次。为了保证在并 * 况下仍然能正常工作,一种思路是使用数据库地锁来防止,就像在多线程环境下所做地一样。总之,要是的查询和修改为一个原子操作,不被其它的访问干扰。MySQL 5 支持存储过程,可以用它来实现。
单条 UPDATE 语句应该原子操作的,可以利用这个特性来保证并发访问情况下队列的正常工作。每次取元素时,先用 UPDATE 修改符合条件的第一行,然后再得到该行。可惜 UPDATE 语句没有返回值,重新用普通的SELECT的话又很难找到刚被改过的那条记录。
这里用到一个小技巧:在 UPDATE 时加上 id=LAST_INSERT_ID(id),再用 SELECT LAST_INSERT_ID() 即可得到刚修改的那条记录的id。还有一个问题,当表中不存在符合条件的记录,导致 UPDATE 失败时,LAST_INSERT_ID() 会保留原来地值不变,因而不能区分队列中是否还有元素。
ROW_COUNT() 返回上一个语句影响的行数,把它作为 SELECT 的一个条件,可以帮助解决这个问题。
最后,支持并发访问的完整解决方案为:


UPDATE targets SET status='D', id=LAST_INSERT_ID(id) WHERE status='C' LIMIT 1;
SELECT * FROM targets WHERE ROW_COUNT()>0 and id=LAST_INSERT_ID();


更新:在实现带优先级的队列时这种方法有问题,带有 ORDER BY ... 条件的 UPDATE 语句非常慢,例如:

UPDATE targets SET status='D' WHERE status='C' ORDER BY schedule ASC LIMIT 1;



而单独查询和更新则是很快的:


SELECT id FROM targets WHERE status='C' ORDER BY schedule ASC LIMIT 1;
UPDATE targets SET status='D' WHERE id='id';



原来这是MySQL的Bug-12915,一年多以前提出来的,虽然关闭了,却只解决了部分问题,尚不支持WHERE,见MySQL 5.0.15 的 Changlog。无奈,上面这种巧妙的方法也没有实用价值了。
最后采用了一种折衷方案,如下:


UPDATE targets, (SELECT id FROM targets WHERE status='C' AND schedule<CURRENT_TIMESTAMP ORDER BY schedule ASC LIMIT 1) tmp SET status='D' WHERE targets.id=LAST_INSERT_ID(tmp.id);
SELECT * FROM targets WHERE ROW_COUNT()>0 and id=LAST_INSERT_ID();
标签:mysql,队列
0
投稿

猜你喜欢

  • 一个Python优雅的数据分块方法详解

    2022-08-22 01:40:04
  • 如何让12px以下的文字最佳显示

    2008-01-24 18:39:00
  • 深入理解Python虚拟机中列表(list)的实现原理及源码剖析

    2022-07-10 22:02:27
  • Python selenium如何设置等待时间

    2023-08-31 18:53:39
  • Anaconda出现CondaHTTPError: HTTP 000 CONNECTION FAILED for url的解决过程

    2021-05-12 11:30:27
  • 详解pycharm的python包opencv(cv2)无代码提示问题的解决

    2022-01-10 06:45:34
  • 安装Pycharm2019以及配置anconda教程的方法步骤

    2021-10-04 18:43:08
  • 利用Python实现Json序列化库的方法步骤

    2023-01-15 07:03:00
  • python 实用工具状态机transitions

    2023-11-06 21:53:41
  • Python结合Selenium简单实现Web自动化测试

    2021-07-24 09:48:21
  • 在ipython notebook中使用argparse方式

    2021-11-17 08:58:41
  • 使用Python生成XML的方法实例

    2022-10-01 19:20:15
  • pycharm配置pyqt5-tools开发环境的方法步骤

    2022-01-05 08:31:00
  • linux centos 7.x 安装 python3.x 替换 python2.x的过程解析

    2021-11-27 02:46:43
  • Python脚本利用adb进行手机控制的方法

    2023-01-31 20:49:47
  • Flask中嵌套启动子线程的方法示例详解

    2023-01-13 21:13:08
  • MySQL5.6安装图解(windows7/8_64位)

    2024-01-12 13:48:00
  • Python开发SQLite3数据库相关操作详解【连接,查询,插入,更新,删除,关闭等】

    2024-01-21 15:16:21
  • Go 高效截取字符串的一些思考

    2024-04-30 10:04:43
  • QQ聊天窗口链接提示效果代码

    2008-12-16 12:59:00
  • asp之家 网络编程 m.aspxhome.com