加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

sql – INSERT语句中的死锁错误

发布时间:2020-12-12 16:34:41 所属栏目:MsSql教程 来源:网络整理
导读:我们有一个基于Web的应用程序.在应用程序中有时间限制的数据库操作(INSERT和UPDATE)需要更多的时间来完成,因此这个特定的流程已经被更改为 Java线程,所以它不会等待(块)完成数据库的完整操作. 我的问题是,如果有超过1个用户遇到这个特定的流,我面临的PostgreS
我们有一个基于Web的应用程序.在应用程序中有时间限制的数据库操作(INSERT和UPDATE)需要更多的时间来完成,因此这个特定的流程已经被更改为 Java线程,所以它不会等待(块)完成数据库的完整操作.

我的问题是,如果有超过1个用户遇到这个特定的流,我面临的PostgreSQL抛出了以下错误:

org.postgresql.util.PSQLException: ERROR: deadlock detected
  Detail: Process 13560 waits for ShareLock on transaction 3147316424; blocked by process 13566.
Process 13566 waits for ShareLock on transaction 3147316408; blocked by process 13560.

上述错误一直在INSERT语句中抛出.

附加信息:
1)我在此表中定义了PRIMARY KEY.
2)表中有FOREIGN KEY引用.
3)将单独的数据库连接传递给每个Java线程.

技术
Web服务器:Tomcat v6.0.10
Java v1.6.0
Servlet的
数据库:PostgreSQL v8.2.3
连接管理:pgpool II

解决方法

处理死锁的一种方法是具有等待随机间隔的重试机制,并尝试再次运行事务.随机间隔是必要的,以便碰撞事务不会持续地相互碰撞,导致所谓的实时锁 – 甚至更难调试.实际上,最复杂的应用程序在需要处理事务序列化失败时,迟早会需要这样的重试机制.

当然,如果你能够确定死锁的原因,通常会更好的消除它,否则会回来咬你.对于几乎所有的情况,即使死锁条件很少,吞吐量和编码开销的一点点就是以确定的顺序获得锁或获得更粗糙的锁,这是值得的,以避免偶然的大的延迟命中和突然的性能悬崖当缩放并发.

当您一直得到两个INSERT语句死锁时,很有可能是唯一的索引插入顺序问题.在两个psql命令窗口中尝试以下示例:

Thread A           | Thread B
BEGIN;             | BEGIN;
                   | INSERT uniq=1;
INSERT uniq=2;     | 
                   | INSERT uniq=2; 
                   |   block waiting for thread A to commit or rollback,to
                   |   see if this is an unique key error.
INSERT uniq=1;     |
   blocks waiting  |
   for thread B,|
     DEADLOCK      | 
                   V

通常解决这个问题的最佳方法是找出保护所有这些事务的父对象.大多数应用程序都有一个或两个主要实体,如用户或帐户,这是一个很好的候选人.那么所有你需要的是每个事务通过SELECT … FOR UPDATE获得它所触摸的主实体上的锁.或者如果触摸几个,那么每次都获得锁定,但是每次都按同样的顺序(按主键排序是一个不错的选择).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读