1. 程式人生 > >資料庫死鎖導致分佈事務中大批量更新資料庫不成功

資料庫死鎖導致分佈事務中大批量更新資料庫不成功

1 問題描述

未簽收的訂單十五天之後自動簽收:總共2個步驟: step1 在樂購系統中批量更新未簽收訂單的狀態,step2: 通過RPC修改訂單系統的訂單狀態, step1和step2放到一個事務中。然後發現step2 訂單DB狀態修改成功,但是step1 樂購db的訂單狀態並未修改。

2 排查過程

  1. 懷疑是程式的問題,檢查樂購系統的執行日誌,發現所有日誌執行成功,db的插入和更新操作日誌以及事務日誌,都顯示執行正確;【正常】
  2. 懷疑是DB執行的問題,檢查DB的binglog日誌,發現沒有事務執行的任何記錄,那資料到底是提交到哪裡去了呢? 樂購系統的日誌明明是顯示執行成功的啊。於是懷疑當時db執行可能有錯誤再檢查db的errorlog發現也沒有任何db執行錯誤資訊;【正常】
  3. 懷疑是db的配置問題,因為我們當時在dev和qa環境下都測試成功,就是boss環境發生這樣的奇怪問題。於是檢查dev,qa和boss環境的所有配置,包括:bulk_insert_buffer_size 批量插入buffer大小,innodb_flush_log_at_trx_commit 事務提交的日誌級別,lock timewait鎖等待時間,注意這個引數很重要。預設是5分鐘吧,我們設定的是365天!!【不正常】
  4. 發現這三個環境沒有db配置沒有任何差別,唯一不同的是線上db做了主從配置。難道主從配置會影響到事務提交的級別,這個也有可能,因為db主從同步會寫binglog日誌,而binglog又是事務執行必須日誌(還有redolog),於是google db主從同步對事務的影響,沒發現任何資訊;【正常】

  5. 這時再重現梳理思路,那就是剩下2種可能:

    1. 樂購系統的資料根本就沒有提交到db,由於網路問題什麼的,如果這種問題的話,spring+mybatis會有錯誤日誌,db超超時問題的(當時準備不行再用tcpdump驗證下3306埠,但是這個問題只能在boss環境出現,沒辦法tcpdump);【正常】
    2. 資料已經到達db了,由於db自身的問題或約束而沒有執行。對,是不是db有啥約束,google之後發現確實有一個引數:max_allowed_packet 這個引數對事務批量提交時資料大小有限制,我們設定的是16m, 難道我們boss環境下事務一次提交的資料超過這個了,檢查了提交記錄資料,開啟128k 位元組,遠遠小於16m。排除這個引數。【正常】
  6. 檢視INNODB狀態日誌:【不正常,DB死鎖】

    SHOW ENGINE INNODB STATUS LATEST DETECTED DEADLOCK
    2015-10-20 16:26:11 7fe0a6aa0700
    *** (1) TRANSACTION:
    TRANSACTION 47995200, ACTIVE 0 sec starting index read
    mysql tables in use 1, locked 1
    LOCK WAIT 3 lock struct(s), heap size 360, 2 row lock(s)
    MySQL thread id 1175573, OS thread handle 0x7fe0a5fa3700, query id 74660997 10.XXX  dev Searching rows for update
    UPDATE tableXX
          SET
          status = 1,success_at = now(),
          update_at = now()
          WHERE refund_no = 'XXX'
          AND status != 1

3 解決問題

  1. 修改db中的 lock timewait鎖等待時間,線上資料即使死鎖也可以快速釋放鎖;
  2. 修改程式,把step2 rpc呼叫修改為非同步執行,注意這樣修改導致事務實際上無效了;

4 總結問題

這裡我們也檢查了我們的程式確實也有問題,一個事務包括在step1和step2中,而step2採用rpc呼叫時間特別長(>2分鐘),這樣導致step1中事務無法及時提交,這個過程中db一直等待commit,而線上資料肯定也會實時更新db,很容易發生死鎖。

又是DB死鎖問題,難道事務中db這麼容易死鎖,這裡推薦一篇阿里大牛的寫的一篇文章,http://hedengcheng.com/?p=844。徹底分析了使用事務中mysql死鎖的問題,原來是頁面死鎖的問題,不是事務死鎖引起的。

還有一個風險就是DB死鎖時,mybatis+spring竟然沒有感知。。日誌打印出來全是成功,太坑了。

相關推薦

資料庫導致分佈事務中大批量更新資料庫成功

1 問題描述 未簽收的訂單十五天之後自動簽收:總共2個步驟: step1 在樂購系統中批量更新未簽收訂單的狀態,step2: 通過RPC修改訂單系統的訂單狀態, step1和step2放到一個事務中。然後發現step2 訂單DB狀態修改成功,但是step1 樂購db的訂單狀態並未修改。 2 排查過程 懷疑是

java程式碼導致事務無法提交

POST /web/aaa/bbb/plan/common/bpms/pmsBpmsOperateAction.do HTTP/1.1 Connection: keep-alive Content-Length: 7620 Accept: application/json, text/javascript,

外來鍵缺乏索引導致的Oracle資料庫

Global Enqueue Services Deadlock detected. More info in file /u01/app/oracle/diag/rdbms/mdmdb/mdmdb1/trace/mdmdb1_ora_2752986.trc.檢視 mdmdb1_ora_2752986.trc

不當事務程式碼引起的資料庫問題

錯誤案例 DBA反映IBANK線上資料庫報警,檢測到死鎖,跟蹤到發生死鎖等待的兩條SQL語句分別為: UPDATE WP_IMAGE_SORT SET GMT_MODIFIED = SYSDATE,IMAGE_IDS = #imageIds# || IMAGE_IDS WHE

關於在專案中遇到MySQL資料庫的問題

在MySQL中, 當一個事務去更新某條資料, 還沒有提交的時候, 第二個事務去更新該資料, 則會出現等待獲取鎖超時異常: >>  Lock wait timeout exceeded; try restarting transaction 此異

資料庫_荔枝_解決方法

轉自高效能mysql;   【1.3.2】死鎖 1)死鎖定義:指兩個或多個事務在同一資源上相互佔用, 並請求鎖定對方佔用的資源,從而導致惡性迴圈的現象; 當多個事務試圖以不同順序鎖定資源時,就可能產生死鎖;多個事務同時鎖定同一個資源時,也會產生死鎖; 2)死鎖解決方法

MySQL資料庫原因及解決

      資料庫和作業系統一樣,是一個多使用者使用的共享資源。當多個使用者併發地存取資料 時,在資料庫中就會產生多個事務同時存取同一資料的情況。若對併發操作不加控制就可能會讀取和儲存不正確的資料,破壞資料庫的一致性。加鎖是實現資料庫並 發控制的一個非常重要的技術。在實

關於oracle資料庫的解決 以及產生的原因

前段時間寫sql語句事物造成了資料庫死鎖,導致所有更新操作無法執行 1.查死鎖 檢視關於鎖的會話資訊 select * from v$session t1, v$locked_object t2 where t1.sid = t2.SESSION_ID   &nb

利用opensips實現freeswitch負載均衡的資料庫問題

多個freeswitch實現負載均衡,要使用同一個資料庫,這樣每個freeswitch都要建立到資料庫的連線,在每個呼叫結束時,都要到資料庫中刪除一些資料,比如要到calls表刪除呼叫資訊,如果多個freeswitch同時進行刪除操作,有可能會產生死鎖,比如: 2018-0

程式設計面試題:編寫一個會造成資料庫的應用

相信對於"開發一個會產生死鎖的Java應用”這類需求,大家都能順利完成。但是如果題目要求得更具體一些,要求這個死鎖發生在資料庫層面,應該怎樣完成呢? 下面我提供一種答案,採用SAP的程式語言ABAP(Advanced Business Application Programming)實現。 我們從ABAP幫

MySQL 5.7.25資料庫

1、檢視innodb狀態 show engine innodb status\G 2、開啟lock_monitor監控 use databases sys; create table innodb_lock_monitor(x int) engine=innodb; 3、查詢程序 m

資料庫及解決方法

死鎖的概念:   死鎖是指兩個或者兩個以上的事務在執行過程中,因爭奪鎖資源而造成的一種互相等待的現象。 死鎖的處理機制:  解決死鎖最有用最簡單的方法是不要有等待,將任何等待都轉化為回滾,並且事務重新開始。但是有可能影響併發效能。 1:超時回滾,即當兩個事務互相等待時,

減少SQLServer資料庫的技巧

如果兩個使用者程序分別鎖定了不同的資源,接著又試圖鎖定對方所鎖定的資源,就會產生死鎖。此時,SQL Server將自動地選擇並中止其中一個程序以解除死鎖,使得另外一個程序能夠繼續處理。系統將回退被中止的事務,並向被回退事務的使用者傳送錯誤資訊。    大多數設計良好的應用都會

資料庫的檢查和解決方法

資料庫死鎖的檢查方法一、         資料庫死鎖的現象程式在執行的過程中,點選確定或儲存按鈕,程式沒有響應,也沒有出現報錯。二、         死鎖的原理當對於資料庫某個表的某一列做更新或刪除等操作,執行完畢後該條語句不提交,另一條對於這一列資料做更新操作的語句在執行的

資料庫原因及解決辦法

死鎖(Deadlock) 所謂死鎖:是指兩個或兩個以上的程序在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的程序稱為死鎖程序。由於資源佔用是互斥的,當某個程序提出申請

select查詢造成的資料庫

     最近給一個客戶更新了一個模組,查詢過程中老是出現查詢結果不一致的情況,有時多有時少,通過除錯發現sql語句都一樣,返回的結果卻不一樣,跟蹤SQL語句發現,在查詢結果少的時候,會報 事務被作為犧牲品的死鎖錯誤,正常情況下,如果報錯會返回null值,為什麼會出現一

頻繁更新基礎資料表造成的資料庫

       最近,有個比較大的專案出現數據庫死鎖。經過分析資料庫trace檔案,發現死鎖的是基礎資料表疾病診斷。根據對應的sql語句找到了問題所在,門診醫生錄入診斷時,程式裡面同時去更新疾病診斷基礎

【疑難系列】 一個看起來是資料庫的問題

起因 週六,7:10,鬧鐘還沒響,客戶電話過來了。 “彬哥,我們XX平臺XX功能導致資料庫死鎖了,上次某某上去看過,把死鎖的sqlserver程序殺過,但還是出現這個問題,麻煩你看一下” “...” 起床,嗽口,吃個西紅柿當早餐,出門(家裡沒網) 經過 連線伺服器,重現問題 問題是: 某功能,點選之後等啊等

SqlDataAdapter.update結合事務(SqlTransaction)批量更新資料

 //此處的程式功能主要是將一個庫中的表資料(源表)更新到另外一個庫中的表資料(目標表) //實現目標表的資料和源表資料一致,已包括增加,更新和刪除資料記錄功能 //主呼叫程式碼塊 SqlConnection conn = new SqlConnection("d

oralce 表被導致ExecuteNonQuery執行無響應,也報錯

在做一個匯入操作時,發現每次執行到一行記錄時就出現ExecuteNonQuery執行無響應,也不報錯,卡住不動了,最後發現是資料表這行資料被鎖了,出現:enq: TX - row lock contention ,有可能是其他系統在操作這個記錄時鎖住了,導致要更新這行記錄時就沒了響應,最