数据库隔离级别
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|
读未提交(read-uncommitted) | 是 | 是 | 是 | 读提交(read-committed) | 否 | 是 | 是 | 可重复读(repeatable-read) | 否 | 否 | 是 | 串行化(serializable) | 否 | 否 | 否 |
假设: A表,trans_date和pid为联合索引主键,B表pid为主键 目前并发情况下,需要将一行数据(主键相同)插入A表。当第一个事务插入成功后,后续事务不在插入,直接拿来用。 (别问为啥不在外面插入好,再并发。这是业务场景需要; 为什么不update锁,因为insert语句无记录锁不住)
代码逻辑为: 当线程1进来时,开启事务1,查询A是否已经存在trans_date和pid数据,存在则直接用,不存在则根据业务逻辑insert一条。 当线程2进来时,开启事务2,查询A是否已经存在trans_date和pid数据,存在则直接用,不存在则根据业务逻辑insert一条。 这个时候,按照正常想法来说,事务1提交后,事务2主键冲突插入报错。
但是如果sql这么写呢
insert into A (
trans_date,
pid,
reserve1,
reserve2
)
select
'20211212',
'1',
' ',
' '
from B where pid='1' and
not exists(select 1 from A where trans_date='20211212'
and pid='1')
加了not exists的判断呢,还会报错吗?
事实如下: 隔离级别为’read-committed’不可重复读时,开启两个事务,都执行插入语句(第一个插入后,第二个执行插入语句会等待),然后第一个事务提交,第二个事务随之报错。
事务隔离级别为 可重复读REPEATABLE-READ时,开启两个事务,都执行插入语句(第一个插入后,第二个执行插入语句会等待),然后第一个事务提交,第二个事务不报错,执行结果影响行数为0。
具体为啥我也不知道。谁能解释一下告诉我。
|