情景模拟:

线程1是一个task,然后分批select数据,然后可能会对这些select的结果进行更新 线程2是一个业务, 它也可能会对这些数据进行update.

问题:如果线程1首先拿到一个数据的快照(MySQL的MVCC),然后开始遍历每行数据来根据业务更新。这时,线程2修改了数据原来的状态。这时线程已经拿到的数据,就会是脏数据了。然后就会导致数据的不一致!

解决办法

方式1

使用 select ... for udpate 来保证数据强一致性(即所谓的悲观锁),还要注意,这种SQL必须要使用到索引,不然会造成表锁。

不过,这容易造成死锁,以及降低性能。

方式2

这种方式,要根据业务具体情况。而不是通用。

也可以在线程1 update的SQL语句中,加上严格的条件判断。 比如,线程1只会更新status < 2的数据。如果线程2修改了status为2,那么这时这次更新就不会再次更新了。线程1的SQL类似:

update xxxx set ststus = (一个小于2的值) where id = xx and status != 2;