MySQL队列的并发读取
一个MySQL表可以被看作是一个队列,其中每个元素。每个查询获取第一行符合条件并将其从表或改变其状态,以便下次查询不会得到它。在没有并发访问的情况下,你可以简单地使用选择从线和修改与更新(或删除)的陈述,你可以实现它。复制代码代码如下所示:
选择*从目标状态= 'c'limit 1;
更新目标状态= 'd'where ID = 'id';
如果有并发访问,可能有其他的选择查询的SELECT和UPDATE语句之间,造成同一排被多次。为了保持在一个并发的情况下工作,一个办法是使用数据库锁来防止它,只是因为它在一个多线程的环境。一句话,如果查询与修改是一个原子操作,不被其他access.mysql 5支持存储过程,可以实现它的干扰。
一个UPDATE语句应该由原子操作,这个功能可以被用来保证并发访问队列的正常工作。每一次元件,第一行满足条件的修改与更新,然后行得到。不幸的是,UPDATE语句不返回值,它是很难找到的记录,已经与普通的选择改变。
这里是一个小技巧:添加ID = last_insert_id(ID)进行更新,然后使用选择last_insert_id()得到的ID,只是修改。另一个问题是,当有不合格记录表中,当更新失败,last_insert_id()将保留原有价值不变,所以它不能区分有队列中的元素。
row_count()返回由前面的语句影响的行数,这可以作为一个条件选择来帮助解决这个问题。
最后,支持并发访问的完整解决方案是:
复制代码代码如下所示:
更新目标状态=会,编号为last_insert_id(ID)在状态= C限制1;
SELECT * FROM目标row_count()> 0和ID = last_insert_id();
更新:当使用优先级实现队列时,这种方法是有问题的…例如,情况非常缓慢:
复制代码代码如下:更新目标状态= 'd'where状态= c按进度ASC限制1;
分离查询和更新很快:
复制代码代码如下所示:
选择ID从目标状态= 'c'order表ASC限制1;
更新目标状态= 'd'where ID = 'id';
原来,这是MySQL的bug-12915,养了一年多前。虽然关门了,但只解决了一些问题。它还不支持哪里。这是MySQL 5.0.15的changlog。然而,上述巧妙的方法没有实用价值。
最后,采用了折衷办法,如下所示:
复制代码代码如下所示:
更新目标,(选择ID从目标状态= 'c'and日程< current_timestamp订单,安排< current_timestamp 1))
SELECT * FROM目标row_count()> 0和ID = last_insert_id();