1. 程式人生 > >Sequelize 事務大併發下造成的死鎖問題。

Sequelize 事務大併發下造成的死鎖問題。

  • 環境
  • Mysql 5.6 Innodb

1.起因

我們有個需要事物的業務場景,上線之初一直執行正常,可是在晚上高峰的時候一直會有邏輯錯誤的問題,剛開始絕的是邏輯有問題。在阿里RDS後臺發現出現大量的鎖,主表的某些資料行持有鎖不釋放,其它的sql一直等待,知道deadlock報錯。因為主表其它業務模組也會用到。所以是一個比較緊急的情況

2.錯誤的程式碼

程式碼可以簡寫為:

DBSequelize.transaction({autocommit:false,isolationLevel:'SERIALIZABLE'}).then(function(t){
    return
db.Tuser.create({...},{transaction:t}); }).then(function(trans){ return db.TuserRelation.update({...},{where:{...},transaction:t}) }).then(function(trans){ return db.Twork.update({...},{where:{...}}) }).then(function(result){ t.commit(res.json(result)); })

大概意思就是如果使用者註冊了一個賬號,就在賬號關係裡增加一個記錄這兩個操作是原子的。無論執行是否成功都會執行
向work表裡新增一條資料。沒併發的情況下,這個邏輯執行是沒有問題的,但是一旦有併發就會出問題。

3.分析錯誤

首先在建立事務的時候我們指定了兩個引數”不自動提交“,”一致性讀“。問題就出現在不自動提交這裡。
剛開始我對事務理解就是:只有我們主動執行commit的時候才會把buffer cache的髒資料寫入磁碟並釋放事務持有的鎖。
但是真是情況不是這樣的。在mysql官方文件中找到了關於autocommit transaction相關描述

By default, MySQL runs with autocommit mode enabled. This means that as soon as you execute a statement that updates (modifies) a table, MySQL stores the update
on disk to make it permanent. The change cannot be rolled back. To disable autocommit mode implicitly for a single series of statements, use the START TRANSACTION statement: START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1; UPDATE table2 SET [email protected] WHERE type=1; COMMIT; With START TRANSACTION, autocommit remains disabled until you end the transaction with COMMIT or ROLLBACK. The autocommit mode then reverts to its previous state.

這裡有幾個概念可以明確:

1.   autocommit的設定是針對session的(一個數據庫連線),如果你對這個這個連線設定了autocommit=1那麼這個連線
   執行的所有sql都會自動commit,反之不會自動提交必須手動commit提交
2. 無論連線設定的autocommit是什麼狀態,在執行事務時候事務裡的autocommit狀態都會被隱式的設定為0,當事物執行
   完成後autocommit會被設定為原先的狀態(執行事務前)

所以我們的問題出現在建立事務時候的{tautocommit=false}這個引數其實是對連線設定的,而不是事務。

在併發的情況下,sequelize連線池的連線是會複用的,假如一個執行了事務的連線去執行其它的DML語句,這些語句是不會提交的
也就是說資料行的鎖不釋放,其它設計到該條資料的DML語句將會被阻塞。造成死鎖。

4.解決

我們只需在事務引數中設定autocommit=true就行了。

相關推薦

Sequelize 事務併發造成問題

環境 Mysql 5.6 Innodb 1.起因 我們有個需要事物的業務場景,上線之初一直執行正常,可是在晚上高峰的時候一直會有邏輯錯誤的問題,剛開始絕的是邏輯有問題。在阿里RDS後臺發現出現大量的鎖,主表的某些資料行持有鎖不釋放,其它的sql一直

Sqoop導表在併發造成RegionServer的系統cpu過高

對於初始時只有一個Region並配置過多的map時,可能會造成某一RegionServer的系統cpu過高,主要原因是多個map任務會通過RPC同時向一個RegionServer寫入資料,當RegionServer的RPC Handler執行緒過少時,其它map端就會等待

併發請求 + 事務巢狀 + 更新資料 =

今有幸為同事排查死鎖問題。 問題描述:一個get介面,內依據引數執行select ... for update,未考慮併發場景,導致程式死鎖,且只要併發請求該介面,幾乎百發百中。 問題定位:   1.檢測資料庫死鎖情況,結果無。   2.介面內無相關共享資源,不會死鎖   3.由於從事許久事務方面工作,所以想

select 時進行update的操作,在高並發引起

xxxx 數據 高並發 select 聚集索引 操作 加鎖 content 其他 場景:當用戶查看帖子詳情時,把帖子的閱讀量:ReadCount+1 select title,content,readcount from post where id=‘xxxx‘ --根

第六章—併發性:和飢餓【計算機作業系統】

6.1 給出可重用資源和可消費資源的例子。 可重用資源:處理器,I/O通道,主存和輔存,裝置以及諸如檔案,資料庫和訊號量之類的資料結構。 可消費資源:中斷,訊號,訊息和I/O緩衝區中的資訊。 6.2 可能發生死鎖所必須的三個條件是什麼? 互斥,佔有且等待,非搶佔。 6.

深入理解分散式事務,高併發分散式事務的解決方案

1、什麼是分散式事務 分散式事務就是指事務的參與者、支援事務的伺服器、資源伺服器以及事務管理器分別位於不同的分散式系統的不同節點之上。以上是百度百科的解釋,簡單的說,就是一次大的操作由不同的小操作組成,這些小的操作分佈在不同的伺服器上,且屬於不同的應用,分散式事務需要保證這

入坑JAVA多執行緒併發(六)

  在多執行緒的中,因為要保證執行緒安全,需要對一些操作進行加鎖,但是如果操作不當,會造成死鎖,導致程式無法執行下去。   形成死鎖的場景:如果有兩個執行緒,執行緒1和執行緒2,執行緒1執行,獲得鎖A,執行緒2執行,獲得B,執行緒1等待鎖B的釋放,執行緒2等待

spinlock造成的原因

舉個例子:程序A中呼叫了spin_lock(&lock)然後進入臨界區,此時來了一箇中斷(interrupt), 該中斷也執行在和程序A相同的CPU上,並且在該中斷處理程式中恰巧也會spin_lock(&lock) 試圖獲取同一個鎖。由於是在

Mysql中update後insert造成的分析

問題描述 sql如下: START TRANSACTION; UPDATE table_a SET ... WHERE id = x ; IF(ROW_COUNT() = 0) THEN INSERT INTO table_a id VALUES x; END I

記因併發事物引起後所展開的問題定位及解決過程

講一些題外話,沒興趣的可直接跳過.首先非常感謝並宣傳一波常常被罵的狗血淋頭卻又覺得異常可愛的暗滅大人.   教會我的太多太多, 但最重要的也是和這篇文章有關聯的就是讓我明白該如何去思考問題, 定位問題, 解決問題.首先介紹下背景,  這邊做的是一對多(包括一對一)的私信功能,

併發listen的連線完成對列backlog太小導致客戶超時,伺服器效率低下

$ /proc/sys/net/core/wmem_max 最大socket寫buffer,可參考的優化值:873200 $ /proc/sys/net/core/rmem_max 最大socket讀buffer,可參考的優化值:873200 $ /proc/sys/net/ipv4/tcp_wmem TCP

HttpClient併發Timeout waiting for connection from pool 問題解決方案

錯誤:org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool 前言  : 第一次看到這個錯誤, 上網找了下,有文章說是連線池不夠了。。。。

併發Timeout waiting for connection from pool 解決方案

當前專案採用SpringCloud分散式架構 , 服務間採用REST介面請求 . 最近頻發連接獲取超時(本質上是HttpClient的連線超時)的問題 , 如下圖 :  這是因為HttpClient在併發量高的時候 , 可能會出現連線池不夠用的情況 .   解決方案如

Boost.mutex連續兩次加造成

問題程式碼如下:#include<iostream> #include<iomanip> using namespace std; #include <boo

MySQL InnoDB等待超時的問題驗證與梳理

MySQL資料庫死鎖問題 例子表 user{id 主鍵name }//PART01 備註:共享鎖之間可以併發執行,排他鎖需要等待其他共享鎖、排他鎖釋放 共享鎖(簡單的select語句不會加鎖) select * from user where id='5' lock in

一般什麼原因會造成,怎麼解決?

作業系統中有若干程序併發執行,它們不斷申請、使用、釋放系統資源,雖然系統的進 程協調、通訊機構會對它們進行控制,但也可能出現若干程序都相互等待對方釋放資源才能 繼續執行,否則就阻塞的情況。此時,若不借助外界因素,誰也不能釋放資源,誰也不能解 除阻塞狀態。根據這樣的情況,作業

pb中如何控制併發和控制

鎖的概述 一. 為什麼要引入鎖 多個使用者同時對資料庫的併發操作時會帶來以下資料不一致的問題: 丟失更新 A,B兩個使用者讀同一資料並進行修改,其中一個使用者的修改結果破壞了另一個修改的結果,比如訂票系統 髒讀 A使用者修改了資料,隨後B使用者又讀出該資料,但

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

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

【Java併發基礎】

前言 我們使用加鎖機制來保證執行緒安全,但是如果過度地使用加鎖,則可能會導致死鎖。下面將介紹關於死鎖的相關知識以及我們在編寫程式時如何預防死鎖。 什麼是死鎖 學習作業系統時,給出死鎖的定義為兩個或兩個以上的執行緒在執行過程中,由於競爭資源而造成的一種阻塞的現象,若無外力作用,它們都將無法推進下去。簡化一點說就

併發程式設計中、遞迴、程序/執行緒池、協程TCP伺服器併發等知識點

1、死鎖 定義; 類似兩個人分別被囚禁在兩間房子裡,A手上拿著的是B囚禁房間的鑰匙,而B拿著A的鑰匙,兩個人都沒法出去,沒法給對方開鎖,進而造成死鎖現象。具體例子程式碼如下: # -*-coding:utf-8 -*- from threading import Thread,Lock,RLoc