Java并发操作MySQL数据库的读写注意
Contents
情景模拟:
线程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;