2017-03-10 30 views
0

您有以下两列一个InnoDB表答:ID(PK),状态MySQL的InnoDB的并发更新

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

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

可能重复[如何处理数据库中的并发更新?](http://stackoverflow.com/questions/1195858/how-to-deal-with-concurrent-updates-in-databases) –

回答

1

InnoDB默认锁定机制是REPEATABLE_READ(见https://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-isolation-levels.html#isolevel_repeatable-read)。这意味着如果你在同一个索引上做两次更新将以原子方式完成,但是我不相信你可以保证哪一次更新会先通过,而无需在你的程序中增加一些逻辑。 (第一次更新将由Thread首先获取锁来完成)。因此,要按照正确的顺序管理更新,您需要实现程序中的逻辑(如果是Java,我会看看Barrier,LatchesSemaphores)。

+0

谢谢!我不太关心这个命令,我担心只有其中的一个更新是可能的(因此,状态= 0)。换句话说,在第一次更新之后,状态值的变化对于获取锁的线程是否可见? – phenompbg

+0

好吧,那么默认情况下两个更新肯定是可能的 – Adonis

+0

是否将事务隔离改为Serializable解决了这个问题? – phenompbg