ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

postgresql 并发update下导致的死锁问题

2020-01-09 21:02:05  阅读:885  来源: 互联网

标签:dubbo java invoke rpc update alibaba 死锁 postgresql com


一、死锁问题背景

在收据批量打印时,由于采用异步并发触发打印,同时触发打印(九千多数据 每隔50ms触发一次),导致了并发执行引起在接口更新打印次数时postgresql发生死锁问题,

具体报错如下:

 1 ### The error occurred while setting parameters
 2 ### SQL: update t_sc_receipt set print_num = coalesce(print_num,0) + 1                       ,print_ts=?
 3 ### Cause: org.postgresql.util.PSQLException: ERROR: deadlock detected
 4   详细:Process 19540 waits for ShareLock on transaction 12520113; blocked by process 19539.
 5 Process 19539 waits for ShareLock on transaction 12520112; blocked by process 19540.
 6   建议:See server log for query details.
 7   在位置:while rechecking updated tuple (329,3) in relation "t_sc_receipt"
 8 ; SQL []; ERROR: deadlock detected
 9   详细:Process 19540 waits for ShareLock on transaction 12520113; blocked by process 19539.
10 Process 19539 waits for ShareLock on transaction 12520112; blocked by process 19540.
11   建议:See server log for query details.
12   在位置:while rechecking updated tuple (329,3) in relation "t_sc_receipt"; nested exception is org.postgresql.util.PSQLException: ERROR: deadlock detected
13   详细:Process 19540 waits for ShareLock on transaction 12520113; blocked by process 19539.
14 Process 19539 waits for ShareLock on transaction 12520112; blocked by process 19540.
15   建议:See server log for query details.
16   在位置:while rechecking updated tuple (329,3) in relation "t_sc_receipt"
17     at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:263)
18     at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
19     at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73)
20     at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:368)
21     at com.sun.proxy.$Proxy57.update(Unknown Source)
22     at org.mybatis.spring.SqlSessionTemplate.update(SqlSessionTemplate.java:254)
23     at com.xxx.framework.mybatis.dao.impl.MyBatisDaoImpl.updateBySql(MyBatisDaoImpl.java:531)
24     at com.xxx.dscsettle.receipt.ReceiptService.updatePrintNum(ReceiptService.java:160)
25     at com.xxx.dscsettle.receipt.ReceiptService$$FastClassBySpringCGLIB$$82e91731.invoke(<generated>)
26     at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
27     at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:651)
28     at com.xxx.dscsettle.receipt.ReceiptService$$EnhancerBySpringCGLIB$$67b6a353.updatePrintNum(<generated>)
29     at com.alibaba.dubbo.common.bytecode.Wrapper72.invokeMethod(Wrapper72.java)
30     at com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory$1.doInvoke(JavassistProxyFactory.java:46)
31     at com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.java:72)
32     at com.alibaba.dubbo.rpc.protocol.InvokerWrapper.invoke(InvokerWrapper.java:53)
33     at com.onlyou.framework.log.DubboLogServiceFilter.invoke(DubboLogServiceFilter.java:28)
34     at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:69)
35     at com.alibaba.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.java:64)
36     at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:69)
37     at com.alibaba.dubbo.rpc.filter.TimeoutFilter.invoke(TimeoutFilter.java:42)
38     at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:69)
39     at com.alibaba.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:75)
40     at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:69)
41     at com.alibaba.dubbo.rpc.protocol.dubbo.filter.TraceFilter.invoke(TraceFilter.java:78)
42     at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:69)
43     at com.alibaba.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:61)
44     at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:69)
45     at com.alibaba.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:132)
46     at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:69)
47     at com.alibaba.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:38)
48     at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:69)
49     at com.alibaba.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:38)
50     at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:69)
51     at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:98)
52     at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:98)
53     at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:170)
54     at com.alibaba.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:52)
55     at com.alibaba.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:81)
56     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
57     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
58     at java.lang.Thread.run(Thread.java:745)
59 Caused by: org.postgresql.util.PSQLException: ERROR: deadlock detected
60   详细:Process 19540 waits for ShareLock on transaction 12520113; blocked by process 19539.
61 Process 19539 waits for ShareLock on transaction 12520112; blocked by process 19540.
62   建议:See server log for query details.

二、原因分析

从报错的提示我们知道了在数据库postgresql发生了死锁(ERROR: deadlock detected  侦测到了死锁发生),而且可以定位是在并发更新打印次数的时候发生的,正常的逻辑下,分页去不断更新收据的打印次数应该是不会出错的,在这边批量更新打印次数时出现了错误。

1.死锁是由于资源的相互竞争引起的,在update数据的时候应该是数据库行锁导致的

2.因为批量修改是一个默认的事务,所以如果没有全部修改完,索引是不会被放开的,所以才会在并发的多次访问中出现死锁,

3.研究出现问题的原因,发现最可能得是重复的行锁导致的,最终才查出原因是因为代码逻辑的原因,未传更新idList,而sql当中又进行了空的判断,导致每次都去更新全部的表数据,由于不同事务直接的相互等待,得不到资源,导致了死锁。

 

三、问题解决与拓展

批量更新的死锁解决方案有以下两种

1.将批量update通过for循环改成单条修改,但是这个方法对服务器的压力增大

2.在更新数据的时候进行一次筛选,将重复的数据剔除出去

在本次问题解决当中,只需将代码中传入正确的idLIst即可解决问题,因为本身进行迭代是没有进行重复upadate的。

疑问:并发update下postgresql就会出现shareLock死锁吗?

一般情况下的多次update应该不会导致死锁,而在事务当中的update则比较可能发生死锁现象。

同时,也看到了一位博主说postgresql 并发update的死锁问题可能是一些版本出现的bug,以及可能可以进行解决的设置以下两个参数进行解决:

autovacuum_vacuum_scale_factor = 0.03
autovacuum_analyze_scale_factor = 0.03


 

参考地址:http://blog.chinaunix.net/uid-20726500-id-4773950.html
https://blog.51cto.com/372550/2387517

 

 

标签:dubbo,java,invoke,rpc,update,alibaba,死锁,postgresql,com
来源: https://www.cnblogs.com/zluckiy/p/12173497.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有