您有一个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;
现在两个线程都可以更新行吗?
在任何一种情况下,如果两行都有可能更新,那么解决这个问题的正确方法是什么?
答案 0 :(得分:1)
InnoDB上默认的锁定机制是 REPEATABLE_READ (参见https://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-isolation-levels.html#isolevel_repeatable-read)。这意味着如果你对同一个索引进行两次更新将以原子方式完成,但是我不相信你可以保证在你的程序中添加一些逻辑时,首先会更新哪个更新。 (第一次更新将由线程首先获取锁定完成。)
因此,要管理更新是按正确顺序完成的,您需要在程序中实现逻辑(如果是Java,我会查看Barrier,Latches和{{ 3}})。