mysql 队列 实现并发读
原文地址:http://www.jb51.net/article/30164.htm
队列是常用的数据结构,基本特点就是先入先出,在事务处理等方面都要用到它,有的时候是带有优先级的队列。当队列存在并发访问的时候,比如多线程情况下,就需要锁机制来保证队列中的同一个元素不被多次获取
一个 MySQL 表可以看作是一个队列,每一行为一个元素。每次查询得到满足某个条件的最前面的一行,并将它从表中删除或者改变它的状态,使得下次查询不会得到它。在没有并发访问的情况下,简单地用 SELECT 得到一行,再用UPDATE(或者DELETE)语句修改之,就可以实现。
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 的一个条件,可以帮助解决这个问题。
最后,支持并发访问的完整解决方案为:
SELECT * FROM targets WHERE ROW_COUNT()>0 and id=LAST_INSERT_ID();
更新:在实现带优先级的队列时这种方法有问题,带有 ORDER BY ... 条件的 UPDATE 语句非常慢,例如:
而单独查询和更新则是很快的:
UPDATE targets SET status='D' WHERE id='id';
原来这是MySQL的Bug-12915,一年多以前提出来的,虽然关闭了,却只解决了部分问题,尚不支持WHERE,见MySQL 5.0.15 的 Changlog。无奈,上面这种巧妙的方法也没有实用价值了。
最后采用了一种折衷方案,如下:
SELECT * FROM targets WHERE ROW_COUNT()>0 and id=LAST_INSERT_ID();
mysql 队列 实现并发读的更多相关文章
- Mysql在高并发情况下,防止库存超卖而小于0的解决方案
背景: 本人上次做申领campaign的PHP后台时,因为项目上线后某些时段同时申领的人过多,导致一些专柜的存货为负数(<0),还好并发量不是特别大,只存在于小部分专柜而且一般都是-1的状况,没 ...
- MySQL事务、并发问题、锁机制
MySQL事务,并发问题,锁机制 1.什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点. 原子性:要不全部成功,要不全部撤销 隔离性:事务之间相互独立,互不干扰 一致性:数据库 ...
- 别再误解MySQL和「幻读」了
The so-called phantom problem occurs within a transaction when the same query produces different set ...
- 【Java面试】这应该是面试官最想听到的回答,Mysql如何解决幻读问题?
"Mysql如何解决幻读问题" 一个工作了4年小伙伴,去一个美团面试,遇到了这样一个问题. 大家好,我是Mic,一个工作了14年的Java程序员 关于这个问题,面试官想考察什么?我 ...
- ios多线程操作(五)—— GCD串行队列与并发队列
GCD的队列能够分为2大类型,分别为串行队列和并发队列 串行队列(Serial Dispatch Queue): 一次仅仅调度一个任务,队列中的任务一个接着一个地运行( ...
- Java多线程 阻塞队列和并发集合
转载:大关的博客 Java多线程 阻塞队列和并发集合 本章主要探讨在多线程程序中与集合相关的内容.在多线程程序中,如果使用普通集合往往会造成数据错误,甚至造成程序崩溃.Java为多线程专门提供了特有的 ...
- Mysql事务,并发问题,锁机制-- 幻读、不可重复读(转)
1.什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点. 原子性:要不全部成功,要不全部撤销 隔离性:事务之间相互独立,互不干扰 一致性:数据库正确地改变状态后,数据库的一致性约 ...
- Mysql事务,并发问题,锁机制-- 幻读、不可重复读--专题
1.什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点. 原子性:要不全部成功,要不全部撤销 隔离性:事务之间相互独立,互不干扰 一致性:数据库正确地改变状态后,数据库的一致性约 ...
- mysql处理高并发,防止库存超卖
先来就库存超卖的问题作描述:一般电子商务网站都会遇到如团购.秒杀.特价之类的活动,而这样的活动有一个共同的特点就是访问量激增.上千甚至上万人抢购一个商品.然而,作为活动商品,库存肯定是很有限的,如何控 ...
随机推荐
- AppCan学习笔记----Request和登录功能简单实现
appcan.ajax(options) 实现appcan中网络数据的上传和获取 发起一个ajax请求,并获取相应的内容 常用参数 options.type: 请求的类型,包括GET.POST等 op ...
- Spring-Boot - 初步搭建
official document:http://projects.spring.io/spring-boot/ 项目代码: https://github.com/chenxing12/springb ...
- Python_Day_05 计数器(counter),有序字典(OrderDict),默认字典(defaultdict),可命名元祖(namedtuple),双向队列(deque),单项队列(deuqe.Queue)
Counter(计数器) 是一个字典的子类,存储形式同样为字典,其中存储的键为字典的元素,值为元素出现的次数,在使用之前我们需要先导入文件 import collections 初始化一个计数器 im ...
- 泛型(Generics)
Framework类库中的泛型 泛型可以使代码重用,提高开发效率 CLR允许在引用类型.值类型或接口中定义泛型方法: CLR允许创建泛型引用类型.泛型值类型(枚举不允许创建).泛型委托类型和泛型接口类 ...
- 初探asp.net异步编程之await
终于毕业了,也顺利进入一家期望的旅游互联网公司.27号入职.放肆了一个多月没写代码,好方啊. 另外一下观点均主要针对于await. 请先看这段话,来自async in C# 5.0. 接下来几个月的 ...
- Oracle数据库优化的经验总结
个人理解,数据库性能最关键的因素在于IO,因为操作内存是快速的,但是读写磁盘是速度很慢的,优化数据库最关键的问题在于减少磁盘的IO,就个 人理解应该分为物理的和逻辑的优化, 物理的是指oracle产品 ...
- Asp.net 面向接口可扩展框架之数据处理模块及EntityFramework扩展和Dapper扩展(含干货)
接口数据处理模块是什么意思呢?实际上很简单,就是使用面向接口的思想和方式来做数据处理. 还提到EntityFramework和Dapper,EntityFramework和Dapper是.net环境下 ...
- 从零开始学Python第六周:面向对象基础(需修改)
标签(空格分隔): 面向对象 一,面向对象基础 (1)面向对象概述 面向过程:根据业务逻辑从上到下写代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类 ...
- Javascript中addEventListener和attachEvent的区别
在利用javascript为DOM Element添加事件处理程序时,如果要想下兼容IE6,7时,就不得不考虑addEventListener与attachEvent的异同. 1.首先说下addEve ...
- 适应手机端的jQuery图片滑块动画DEMO演示
在线预览 下载地址 实例代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "htt ...