MySQL InnoDB并发更新

时间:2017-03-10 09:07:17

标签: mysql multithreading

您有一个InnoDB表A,其中包含以下两列:id(PK),status

两个线程按以下顺序访问表:

Thread 1: SELECT id from A where status = 0 LIMIT 1;
Thread 2: SELECT id from A where status = 0 LIMIT 1;

两个线程都选择id 1。

Thread 1: UPDATE A SET status = 1 WHERE id = 1 AND status = 0;
Thread 2: UPDATE A SET status = 2 WHERE id = 1 AND status = 0;

两个线程是否有可能更新同一行?

现在添加交易:

Thread 1: SELECT id from A where status = 0 LIMIT 1;
Thread 2: SELECT id from A where status = 0 LIMIT 1;
Thread 1: START TRANSACTION;
Thread 2: START TRANSACTION;
Thread 1: UPDATE A SET status = 1 WHERE id = 1 AND status = 0;
Thread 2: UPDATE A SET status = 2 WHERE id = 1 AND status = 0;
Thread 1: COMMIT;
Thread 2: COMMIT;

现在两个线程都可以更新行吗?

在任何一种情况下,如果两行都有可能更新,那么解决这个问题的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

InnoDB上默认的锁定机制是 REPEATABLE_READ (参见https://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-isolation-levels.html#isolevel_repeatable-read)。这意味着如果你对同一个索引进行两次更新将以原子方式完成,但是我不相信你可以保证在你的程序中添加一些逻辑时,首先会更新哪个更新。 (第一次更新将由线程首先获取锁定完成。)

因此,要管理更新是按正确顺序完成的,您需要在程序中实现逻辑(如果是Java,我会查看BarrierLatches和{{ 3}})。