主键冲突和数据库隔离级别有关?

数据库隔离级别

事务隔离级别脏读不可重复读幻读
读未提交(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’不可重复读时,开启两个事务,都执行插入语句(第一个插入后,第二个执行插入语句会等待),然后第一个事务提交,第二个事务随之报错。(oracle默认隔离级别是RC)

事务隔离级别为 可重复读REPEATABLE-READ时,开启两个事务,都执行插入语句(第一个插入后,第二个执行插入语句会等待),然后第一个事务提交,第二个事务不报错,执行结果影响行数为0。(mysql默认隔离级别RR)

总结,mysql不报错,oracle报错。


具体为啥我也不知道。谁能解释一下告诉我。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值