原文地址:http://www.jb51.net/article/30164.htm

队列是常用的数据结构,基本特点就是先入先出,在事务处理等方面都要用到它,有的时候是带有优先级的队列。当队列存在并发访问的时候,比如多线程情况下,就需要锁机制来保证队列中的同一个元素不被多次获取

一个 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 队列 实现并发读的更多相关文章

  1. Mysql在高并发情况下,防止库存超卖而小于0的解决方案

    背景: 本人上次做申领campaign的PHP后台时,因为项目上线后某些时段同时申领的人过多,导致一些专柜的存货为负数(<0),还好并发量不是特别大,只存在于小部分专柜而且一般都是-1的状况,没 ...

  2. MySQL事务、并发问题、锁机制

    MySQL事务,并发问题,锁机制 1.什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点. 原子性:要不全部成功,要不全部撤销 隔离性:事务之间相互独立,互不干扰 一致性:数据库 ...

  3. 别再误解MySQL和「幻读」了

    The so-called phantom problem occurs within a transaction when the same query produces different set ...

  4. 【Java面试】这应该是面试官最想听到的回答,Mysql如何解决幻读问题?

    "Mysql如何解决幻读问题" 一个工作了4年小伙伴,去一个美团面试,遇到了这样一个问题. 大家好,我是Mic,一个工作了14年的Java程序员 关于这个问题,面试官想考察什么?我 ...

  5. ios多线程操作(五)—— GCD串行队列与并发队列

          GCD的队列能够分为2大类型,分别为串行队列和并发队列      串行队列(Serial Dispatch Queue):      一次仅仅调度一个任务,队列中的任务一个接着一个地运行( ...

  6. Java多线程 阻塞队列和并发集合

    转载:大关的博客 Java多线程 阻塞队列和并发集合 本章主要探讨在多线程程序中与集合相关的内容.在多线程程序中,如果使用普通集合往往会造成数据错误,甚至造成程序崩溃.Java为多线程专门提供了特有的 ...

  7. Mysql事务,并发问题,锁机制-- 幻读、不可重复读(转)

    1.什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点. 原子性:要不全部成功,要不全部撤销 隔离性:事务之间相互独立,互不干扰 一致性:数据库正确地改变状态后,数据库的一致性约 ...

  8. Mysql事务,并发问题,锁机制-- 幻读、不可重复读--专题

    1.什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点. 原子性:要不全部成功,要不全部撤销 隔离性:事务之间相互独立,互不干扰 一致性:数据库正确地改变状态后,数据库的一致性约 ...

  9. mysql处理高并发,防止库存超卖

    先来就库存超卖的问题作描述:一般电子商务网站都会遇到如团购.秒杀.特价之类的活动,而这样的活动有一个共同的特点就是访问量激增.上千甚至上万人抢购一个商品.然而,作为活动商品,库存肯定是很有限的,如何控 ...

随机推荐

  1. SQL Server 存储过程中处理多个查询条件的几种常见写法分析,我们该用那种写法

    本文出处: http://www.cnblogs.com/wy123/p/5958047.html 最近发现还有不少做开发的小伙伴,在写存储过程的时候,在参考已有的不同的写法时,往往很迷茫,不知道各种 ...

  2. 为.NET搭建Linux的开发环境,鄙视那些将简单事情复杂化的人

    写在前面的吐槽 原本跨平台开发很容易的事情, 很多人把它弄得很麻烦,给外人的感觉:你们.NET跨平台开发好不成熟,好麻烦哦. ..................................... ...

  3. MS SQL Server中数据表、视图、函数/方法、存储过程是否存在判断及创建

    前言 在操作数据库的时候经常会用到判断数据表.视图.函数/方法.存储过程是否存在,若存在,则需要删除后再重新创建.以下是MS SQL Server中的示例代码. 数据表(Table) 创建数据表的时候 ...

  4. [Excel] WorkBook.SaveAs

    ExcelApplication.WorkBook.SaveAs(Filename, FileFormat, Password, WriteResPassword, ReadOnlyRecommend ...

  5. bootstrap-简单实用的垂直手风琴滑动菜单列表特效

    前端: <html lang="zh"> <head> <meta charset="UTF-8"> <meta ht ...

  6. [调整] Firemonkey iOS 原生 Edit 透明框, 改变框色

    说明:iOS 原生 Edit 透明框 适用:Berlin Firemonkey 方法:在 StyleLookup 输入 transparentedit 效果: 如果有图片 Image 在这二个 Edi ...

  7. 【转】mysql_fetch_row , mysql_fetch_array , mysql_fetch_assoc 的区别

    <?php $link = mysql_connect('localhost', 'root', ”); mysql_select_db('abc', $link); $sql = “selec ...

  8. 21、ASP.NET MVC入门到精通——ASP.NET MVC4优化

    本系列目录:ASP.NET MVC4入门到精通系列目录汇总 删除无用的视图引擎 默认情况下,ASP.NET MVCE同时支持WebForm和Razor引擎,而我们通常在同一个项目中只用到了一种视图引擎 ...

  9. 利用SCORE法则来总结一次偷懒的单元测试过程

    最近遇到一个单元测试的问题,本周正好学个了一个SCORE法则,这里正好练练手应用此法则将问题的前因后果分享给大家. S:背景  代码要有单元测试,检测的标准就是统计代码的单元测试覆盖率,程序员需要达到 ...

  10. thinkcmf 常用操作

    11-16  thinkcmf 核心文件结构:simplewind--model--lite--model.class.php /controller.class.php Mobile---contr ...