可以这样理解Mysql中的查询操作:

一个 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 sche

dule 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

SELECT * FROM targets WHERE ROW_COUNT()>0 and id=LAST_INSERT_ID();

c mysql 并发处理_mysql队列中实现并发读的实现方法解析相关推荐

  1. java抢单功能_基于消息队列的高并发抢单功能实现方法与流程

    本发明涉及嵌入式软件中间件,具体涉及一种基于消息队列的高并发抢单功能实现方法. 背景技术: 中间件是一种独立的系统软件或服务程序,分布式应用系统借助这种软件在不同的技术之间共享资源,管理计算资源和网络 ...

  2. idea 断点线程_在IntelliJ IDEA中多线程并发代码的调试方法

    通常来说,多线程的并发及条件断点的debug是很难完成的,或许本篇文章会给你提供一个友好的调试方法.让你在多线程开发过程中的调试更加的有的放矢. 我们将通过一个例子来学习.在这里,我编写了一个多线程程 ...

  3. mysql 统计条目_mysql 统计表中条目数量的几种方法

    mysql 统计表中条目数量的几种方法 展开 通常的方法是: select count(*) from `table_name` select count(1) from `table_name` s ...

  4. mysql from_unixtime(_MySQL 数据库中日期与时间函数 FROM_UNIXTIME(), UNIX_TIME()

    jinlinlucky:二.多路处理模块的配置说明|@||@|Apache HTTP服务器是一个强大的.灵活的能够在多种平台.不同环境下运行的Web服务器.由于不同的平台和不同的环境经常产生不同的需求 ...

  5. thinkphp mysql 预处理_thinkPHP框架中执行原生SQL语句的方法

    本文实例讲述了thinkPHP框架中执行原生SQL语句的方法.分享给大家供大家参考,具体如下: 怎样在thinkphp里面执行原生的sql语句? $Model = new Model();//或者 $ ...

  6. java web配置dll文件_JavaWeb项目中dll文件动态加载方法解析(详细步骤)

    相信很多做Java的朋友都有过用Java调用JNI实现调用C或C++方法的经历,那么Java Web中又如何实现DLL/SO文件的动态加载方法呢.今天就给大家带来一篇JAVA Web项目中DLL/SO ...

  7. c++中文件的读处理多种方案解析

    C++中读文件的方法 1. 读文件准备工作 2. 读取文件的3种方法举例说明 1.getline()全局函数 2. 流输入方式ifs<\ 1. 读文件准备工作 1.前提,首先读文件需要引入头文件 ...

  8. repeat mysql翻译_MySQL数据库中系统函数repeat有哪些功能呢?

    摘要: 下文讲述MySQL数据库中系统函数repeat的功能说明,如下所示: 系统函数repeat的功能: repeat函数的功能: 重复前面字符串指定次数 repeat语法: repeat(str, ...

  9. C mysql添加_MYSQL将表 B C 插入表A方法

    具体情形是:有三张表a.b.c,现在需要从表b和表c中分别查几个字段的值插入到表a中对应的字段.对于这种情况,我们可以使用如下的语句来实现: 1.INSERT INTO db1_name(field1 ...

最新文章

  1. 树莓派/PC实现实时摄像头数据共享(Python—picamera)
  2. [C#]统计文本文件txt中的行数(快速读取)
  3. 如何使用ember下拉框组件??
  4. ETSI GS MEC 014,UE 标识 API
  5. python处理流程-python的处理流程
  6. oracle导出库压缩参数,oracle数据库的定时备份:导出 压缩 归类
  7. Swif基础语法01
  8. NoNode for /hbase/hbaseid解决方案
  9. android 强制下线功能,Android学习之基础知识八—Android广播机制实践(实现强制下线功能)...
  10. Ubuntu中Go的环境搭建
  11. MCTS人工智能围棋
  12. it论坛 计算机科学概论,(毕业论文) 计算机科学与技术专业 IT技术论坛.doc
  13. selenium模块
  14. 如何用Python画出玫瑰曲线和蝴蝶曲线
  15. 免费的在线3D CAD【BimAnt】
  16. 函数编程之Function
  17. Java中HashMap底层实现原理
  18. QRJDC搭建实现QQ扫码登录对接青龙对接傻妞
  19. China-pub使我出离愤怒
  20. Acrobat Pro DC 教程:了解 Acrobat Pro DC 界面

热门文章

  1. VMware workstation 磁盘扩容
  2. Stanford机器学习---第十一讲.异常检测
  3. 【报告分享】2019年中国人工智能商业落地研究报告.pdf(附下载链接)
  4. (Object detection)目标检测从入门到精通——第五部分YOLO 算法
  5. 【问答集锦】联邦学习让隐私保护和海量数据学习兼得!
  6. HDU3544 不平等博弈
  7. windows删文件:找不到该项目,该项目不在xx中,请确认位置,然后重试 的解决方案
  8. Leetcode每日一题:118 + 119.pascals-triangle I and II(杨辉三角1和2)
  9. LeetCode每日一题:14.longest-common-prefix(最长公共前缀)
  10. 蓝桥杯 基础练习 报时助手