`

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 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();
分享到:
评论

相关推荐

    q4m mysql队列处理 安装

    q4m mysql队列处理 (文本打开即可)

    mysql 队列 实现并发读

    总的来说,实现并发读的MySQL队列涉及对数据库特性的深入理解,包括事务、锁、`LAST_INSERT_ID()`、`ROW_COUNT()`以及优化查询性能。在实际应用中,应根据具体需求和数据库版本选择合适的方法,确保并发访问时的队列...

    queuezilla:使用 MySQL 队列的框架

    QueueZilla 是一个简单的框架,使您能够快速、整洁地编写 MySQL 队列使用者。 它通过接口强制执行关键方法,因此您可以编写干净的代码 安装 运行composer require fobilow/queuezilla 1.*或将"fobilow/queuezilla" ...

    队列写入mysql实例

    本实例将探讨如何利用`LinkedBlockingQueue`和Redis队列来实现数据写入MySQL的过程,这对于大型系统中的批量数据处理和并发控制具有重要意义。 首先,`LinkedBlockingQueue`是Java并发库`java.util.concurrent`中的...

    CVI_mysql_Interface.rar_CVI 队列实现_CVI数据库_MySQL CVI_cvi mysql_cvi

    本程序开发环境为labwindows/CVI,主要是提供基于CVI虚拟仪器数据采集的MySQL数据库接口,利用双循环缓冲队列,实现了对MySQL数据库的数据更新。并提供了数据删除算法,解决了数据库数据更新速度慢的问题。

    Laravel开发-l4mysqlqueue

    相比于默认的内存驱动(如Beanstalkd或Redis),MySQL队列驱动提供了一个更易于设置和管理的选项,尤其是对于那些已经使用MySQL作为主要数据库的项目。 首先,要使用这个驱动,你需要在你的`app/config/queue.php`...

    集群聊天服务器(nginx tcp负载均衡模块、muduo网络库、基于发布-订阅的redis消息队列、mysql数据库).zip

    集群聊天服务器(nginx tcp负载均衡模块、muduo网络库、基于发布-订阅的redis消息队列、mysql数据库) 集群聊天服务器(nginx tcp负载均衡模块、muduo网络库、基于发布-订阅的redis消息队列、mysql数据库) 集群聊天...

    代码:kafka数据接入到mysql中

    在大数据处理领域,将Kafka数据接入到MySQL中是一个常见的需求。Kafka作为一个高吞吐量、分布式的实时消息发布订阅系统,常用于日志收集、流式数据处理等场景。而MySQL则作为广泛应用的关系型数据库,用于持久化和...

    Yii2 队列 shmilyzxt/yii2-queue 简单概述

    1.我用的yii2高级版,我们从配置开始看代码,这里我用的是mysql队列,首先配置文件,我把queue配置项写在根目录common\config\main-local.php下的 components数组下,更改一下数据库配置.复制composer安装后复制 vendor\...

    PHP+MySQL实现消息队列的方法分析

    当面对需要高效、稳定地发送大量短信的服务时,利用PHP和MySQL构建一个消息队列系统是解决这一问题的有效方式。本文将从以下几个方面详细介绍PHP+MySQL实现消息队列的方法和相关技巧。 一、消息队列的概念 消息队列...

    基于spring 消息队列

    6. **数据持久化**:消费者从队列中取出消息后,需要将数据持久化存储,例如使用数据库(如MySQL、MongoDB等)。Spring提供了JPA(Java Persistence API)和MyBatis等持久层框架,可以帮助开发者方便地完成数据的...

    python基于mysql实现的简单队列以及跨进程锁实例详解

    在本文中,我们将探讨如何利用MySQL数据库来实现一个简单的队列系统以及跨进程锁,以解决多进程之间的资源同步问题。 首先,我们要建立一个基于MySQL的简单任务队列。队列在多进程环境中的作用是存储待处理的任务,...

    mysql-oracle数据同步

    实时同步通常通过触发器、消息队列或者中间件实现,确保数据一旦在源数据库更新,目标数据库立即得到同步。批量同步则是在特定时间点进行一次性的大量数据迁移,比如在业务低峰期。 对于“mysql-oracle数据同步”这...

    mysql-async PHP 异步 MySQL 客户端

    任务队列是另一个增强MySQL-Async效率的工具。它允许开发者将数据库操作放入队列,然后由后台进程按顺序执行。这样,即使在高并发情况下,也不会因为大量的并发请求而导致数据库服务器过载。任务队列还有助于实现...

    针对java、mysql、redis、消息队列开发的一款面经、题型的应试网站

    【标题】中的“针对java、mysql、redis、消息队列开发的一款面经、题型的应试网站”表明这是一个专为准备Java、MySQL、Redis和消息队列面试者设计的在线学习平台。这个网站可能包含了各种面试问题、实战练习以及相关...

    canal + mysql + rabbitmq步骤(CanalListener)

    Canal是一款由阿里巴巴开源的、基于MySQL binlog的增量日志订阅与消费组件,它能够监听MySQL数据库的增删改查操作,并将这些变更事件转发到各种目标系统,如RabbitMQ消息队列。本教程将详细介绍如何配置Canal监听...

    PHP消息队列实现及应用.txt

    讲解消息队列用于解耦的案例,使用mysql的一个表,做为队列存储,来实现成中间件来解耦订单系统和配送系统。使用订单系统实时写入,并用定时任务启动配送系统的处理程序,对队列进行处理并标记结果,使两个业务系统...

Global site tag (gtag.js) - Google Analytics