有时候,我们经常会写这样的逻辑,insertOrUpdate,即数据存在即更新,数据不存在则增加。
一般情况下这个是没有问题,但是在部分情况,这个东西是存在很大的问题的
我们都知道,数据库有4个隔离级别,即
READ UNCOMMITED
READ COMMITED
REPEATABLE READ
SERIALIZABLE
按照正常的逻辑,
针对READ UNCOMMITED,我们用insertOrUpdate,事务更新,是没有问题的
针对READ COMMITED,我们用insertOrUpdate,事务更新,是没有问题的
针对REPEATABLE READ,我们用insertOrUpdate,事务更新,是没有问题的,但是不建议对同一条语句频繁操作,当两个事务同时执行select时,一个事务再执行update,就会造成死锁
针对SERIALIZABLE,我们用insertOrUpdate,事务更新,是没有问题的
但是呢,MYSQL对REPEATABLE READ有额外的处理方案
了解过隔离离别的人都知道,REPEATABLE READ解决重复读的问题,即读的时候加共享锁,写的时候加排它锁,SERIALIZABLE解决的是幻读的问题,即select count(*) from table where column_a = 'XX'的值不变的情况。但是MYSQL的Repeatable Read级别解决了部分Serialzable需要解决的问题,在使用时需要注意,即GAP锁,Next Key 锁
解决方案:
1、降低隔离级别为READ COMMITED
2、将insertOrUpdate不要单事务执行,分为两个事务即可
3、改为乐观锁
4、提高隔离级别为SERIALIZABLE,这个方法不太建议,仅在并发不高的情况下可采用