简体   繁体   English

一致的读取和更新,而无需在MySQL / InnoDB中锁定表

[英]Consistent read and update without table locking in MySQL/InnoDB

I need to perform the following on MySQL/InnoDB. 我需要在MySQL / InnoDB上执行以下操作。 Assume I have a table consists of 3 cols (id, counter, status) 假设我有一个表,包含3个列(ID,计数器,状态)

I need to: 我需要:

  1. Select rows where status = 0 选择状态为0的行
  2. Update them by setting status = 1, and increment counter by 1 通过将状态设置为1来更新它们,并将计数器增加1
  3. Return the selected/updated id to client 将所选/更新的ID返回给客户端

Requirements: 要求:

  • The rows to be update must exactly the same with selected, even new rows has been added after the 1st select 要更新的行必须与所选行完全相同,即使在第一个选择之后添加了新行
  • No duplicated update on a row is allowed, even multiple scripts are running on the same data at the same time 不允许连续重复更新,即使多个脚本同时在同一数据上运行

What would be the best solution in term of performance and scalability (work for large table)? 在性能和可伸缩性(适用于大型表)方面,什么是最佳解决方案?

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
START TRANSACTION;
SELECT  id
FROM    mytable
WHERE   status = 0
FOR UPDATE;
UPDATE  mytable
SET     status = 1,
        cnt = cnt + 1
WHERE   status = 0;
COMMIT;

You can select and update in one statement, which should execute atomically: 您可以在一条语句中选择和更新,该语句应自动执行:

UPDATE tbl SET status=1, counter=counter+1 WHERE status=0;

I don't know what you want in step 3, since more than one id is involved. 我不知道您在第3步中想要什么,因为涉及多个ID。 Do you want a table of id rows as from a SELECT statement? 您是否要使用SELECT语句中的ID行表? If so, you can perhaps use a stored procedure, or else use SELECT ... LOCK IN SHARE MODE 如果是这样,则可以使用存储过程,也可以使用SELECT ... LOCK IN SHARE MODE

You can do 你可以做

SELECT  id
FROM    mytable
WHERE   status = 0
FOR UPDATE;

Then build list of ids in your software and then do 然后在您的软件中构建ID列表,然后执行

UPDATE  mytable
SET     status = 1,
        cnt = cnt + 1
WHERE   id IN (...)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM