如果不存在MySQL中使用需要注意什么

  介绍

小编给大家分享一下MySQL中使用如果不存在需要注意什么,希望大家阅读完这篇文章之后都有所收获、下面让我们一起去探讨吧!



环境MySQL 5.6.14
事务隔离级别读提交
事务的开启和结束由JAVA程序控制。

上次报死锁的过程,抽象如下

<李>

delimitr $ $

<李>

创建过程“test_proc”(

<李>

  ,,,pid int

<李>

)

<李>

  开始

<李>

  ,,,如果不存在(select *从t id=pid)然后

<李>

  ,,,,,,,插入t (id)值(pid);

<李>

  ,,,如果,

<李>

  ,,,

<李>

  ,,,更新t组总=总+ 1 id=pid;

<李>

结束$ $

<李>

  分隔符,,


死锁原因已经明白了,就是并发情况下,插入遇到排它锁,则尝试加共享锁。
在最后更新的时候,两个持有共享锁的连接,都尝试申请排它锁,则导致了死锁。

但是问题是…怎么会走到了最后一行的更新语句?
另外两个连接,不是应该在插入语句时报,重复的条目& # 39;xx # 39;关键& # 39;主要# 39;错误吗?

问题应该出在这种结构里
如果不存在(select *从t id=pid)然后
,,xxx
结束如果;

使用如果不存在模式,真心要注意啊。在这种结构里出现的异常,不会报的错,而是直接跳出如果判断,继续执行! !

实验准备


<李>

创建表“t”(

<李>

  “id”才能int(11)不是NULL,

<李>

  “总”才能int (11) NOT NULL默认& # 39;0 & # 39;

<李>

  主键才能(id)

<李>

)引擎=InnoDB默认字符集=utf8mb4;

<李>


<李>

截断表t;

<李>

下降过程中如果存在test_proc;

<李>

  分隔符$ $

<李>

创建过程“test_proc”(

<李>

  ,,,pid int,

<李>

  ,,,是int

<李>

)

<李>

开始

<李>

  ,,,如果不存在(select *从t id=pid)然后

<李>

  ,,,,,,,插入t (id、总)值(pid是);

<李>

  ,,,,,,,更新t组总=是+ 1,id=pid;

<李>

  ,,,如果,

<李>

  ,,,选择是+ 1,,,,,

<李>

结束$ $

<李>

  李分隔符;


打开三个客户端,分别执行过程
 MySQL中使用如果不存在需要注意什么”> <br/> <br/>第一个客户端执行,并没有提交。<br/>第二,第三客户端处于阻塞状态。<br/>等第一个客户端提交,<br/> <br/>第二个客户端返回201 <br/>第三个客户端返回301 <br/>且没有任何的报错信息。<br/> <br/> <br/>三个客户端都提交之后,查看T表信息<br/>只有一个记录,id为1,总数为101 <br/> <br/>也就是说,第二个,第三个客户端,在得到主键冲突的异常后,没有报的错,没有继续执行如果块内剩下的语句,而是直接跳出了如果块,继续执行如果块外的语句! ! <br/> <br/>该报错的地方不报的错,在大段的存储过程中,导致死锁还是小问题,就怕引起数据的错,乱而不自知。<br/> <br/>针对这种情况,如果有主键或者唯一约束,我觉得干脆改为如下的方式。<br/>分隔符$ $ <br/>创建过程“test_proc”(<br/>,,,, pid int, <br/>,,,,是int <br/>) <br/> <br/>开始,,,,插入t (id、总)值(pid是);<br/>,,,,更新t组总=是+ 1,id=pid; <br/>,,,,选择是+ 1;<br/>结束$ $ <br/>分隔符;<br/> </p> <p class=看完了这篇文章,相信你对“MySQL中使用如果不存在需要注意什么”有了一定的了解,如果想了解更多相关知识,欢迎关注行业资讯频道,感谢各位的阅读!

如果不存在MySQL中使用需要注意什么