zoukankan      html  css  js  c++  java
  • 【疑难系列】 一个看起来是数据库死锁的问题

    起因

    周六,7:10,闹钟还没响,客户电话过来了。

    “彬哥,我们XX平台XX功能导致数据库死锁了,上次某某上去看过,把死锁的sqlserver进程杀过,但还是出现这个问题,麻烦你看一下”

    “...”

    起床,嗽口,吃个西红柿当早餐,出门(家里没网)

    经过

    连接服务器,重现问题

    问题是:

    某功能,点击之后等啊等,等啊等,等死了都没等到响应

    所以

    上次某某上去看过

    使用这句sql查询到有被锁的连接

    -- 查询死锁
    select    
        request_session_id spid,   
        OBJECT_NAME(resource_associated_entity_id) tableName    
    from    
        sys.dm_tran_locks   
    where    
        resource_type='OBJECT'
    

    于是将查询出来的死锁进程杀掉——但结果没用

    凡是这种线程问题,都可以上jstack

    找到java进程id,上jstack工具查看

    D:Program FilesJavajdk1.8in>jstack 15316 > jstatck.log
    

    将日志文件jstatck.log,拷贝到本地打开查看,

    "http-nio-8080-exec-25" #197 daemon prio=5 os_prio=0 tid=0x0000000041b70800 nid=0x1530 waiting on condition [0x000000005f67f000]
       java.lang.Thread.State: TIMED_WAITING (parking)
    	at sun.misc.Unsafe.park(Native Method)
    	- parking to wait for  <0x00000003c66f3d98> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
    	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
    	at java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:467)
    	at org.apache.tomcat.util.threads.TaskQueue.poll(TaskQueue.java:85)
    	at org.apache.tomcat.util.threads.TaskQueue.poll(TaskQueue.java:31)
    	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1073)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    	at java.lang.Thread.run(Thread.java:748)
    

    这种java库的线程不用看,看我们自己写的代码部分

    "http-nio-8080-exec-19" #191 daemon prio=5 os_prio=0 tid=0x000000003d743800 nid=0xce0 runnable [0x000000005ee5b000]
       java.lang.Thread.State: RUNNABLE
    	at java.net.SocketInputStream.socketRead0(Native Method)
    	at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    	at java.net.SocketInputStream.read(SocketInputStream.java:171)
    	at java.net.SocketInputStream.read(SocketInputStream.java:141)
    	at org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:137)
    	at org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:153)
    	at org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:282)
    	at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:140)
    	at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57)
    	at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259)
    	at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:163)
    	at org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:153)
    	at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:273)
    	at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
    	at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:254)
    	at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
    	at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86)
    	at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
    	at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
    	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    	at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
    	at 我们公司的代码.RestHandler.httpExecute(RestHandler.java:50)
    	at 我们公司的代码.RestHandler.operatorToXXZX(RestHandler.java:44)
    	at 我们公司的代码.ShortTermForecastService.saveToCIMISS(ShortTermForecastService.java:334)
    	...(其它省略)
    
    

    在这里找到了与我们公司的代码相关的内容。

    这里表明两个问题:

    1. 说明这个线程正在运行,与上述“等啊等,等啊等”的现象描述是一致的(没有运行完的线程不就这样么)

    2. 这里的代码在访问某个url,并且一直在等待对方的响应

    找到了出问题的地方,就可以查看源代码分析了

    private void saveToCIMISS(final Long fid) throws Exception {
            //... 省略上面代码
            RestHandler.operatorToXXZX(EnumXXZX.INS_SHORTTREMPRODUCT.getUrl(), EnumXXZX.INS_SHORTTREMPRODUCT.getInterfaceId(), param);
            //...省略下面代码
        }
    

    然后看看是调用了哪个 url 导致,至此问题原因已找到!

    结果及分析

    为什么会有“死锁”sqlserver连接呢

    其实这并不是什么“死锁”,只是正常的锁

    上面这个线程执行过程,会使用事务,事务引进的锁——而因为在事务过程中产生了外部的http访问,且该http长时间没有响应,导致事务锁因此也长时间占用数据库。

    所以,表面看起来是数据库“死锁”了

    解决问题思路

    凡是线程问题,都可以用jstack工具

    其它

    面试的时候,面试官问我

    “你遇到过最难解决的问题,你是怎么解决的?”

    “我特么都是问题解决了就忘记了,所以没啥印象”

    不过,我是在心里说的

    所以,对于别人问我的问题,我决定记录下来,免得将来忘记了

  • 相关阅读:
    为什么今天的L4无人驾驶无法到达终局(转)
    各种卷积类型Convolution
    关于快速、深入理解需求
    测试注意事项及工作标准
    测试工作指引
    测试验收工作指引
    Jmeter的json提取器使用
    高等数学:第一章 函数与极限
    vscode
    Python模块查找路径
  • 原文地址:https://www.cnblogs.com/binblog/p/11026561.html
Copyright © 2011-2022 走看看