mysql 死锁原因_Mysql并发时经典常见的死锁原因及解决方法
1.mysql都有什么鎖
MySQL有三種鎖的級別:頁級、表級、行級。
表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖沖突的概率最高,并發度最低。
行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖沖突的概率最低,并發度也最高。
頁面鎖:開銷和加鎖時間界于表鎖和行鎖之間;會出現死鎖;鎖定粒度界于表鎖和行鎖之間,并發度一般
算法:
next KeyLocks鎖,同時鎖住記錄(數據),并且鎖住記錄前面的Gap
Gap鎖,不鎖記錄,僅僅記錄前面的Gap
Recordlock鎖(鎖數據,不鎖Gap)
所以其實 Next-KeyLocks=Gap鎖+ Recordlock鎖
2.什么情況下會造成死鎖
所謂死鎖: 是指兩個或兩個以上的進程在執行過程中,
因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去.
此時稱系統處于死鎖狀態或系統產生了死鎖,這些永遠在互相等竺的進程稱為死鎖進程.
表級鎖不會產生死鎖.所以解決死鎖主要還是針對于最常用的InnoDB.
死鎖的關鍵在于:兩個(或以上)的Session加鎖的順序不一致。
那么對應的解決死鎖問題的關鍵就是:讓不同的session加鎖有次序
3.一些常見的死鎖案例
案例一:
需求:將投資的錢拆成幾份隨機分配給借款人。
起初業務程序思路是這樣的:
投資人投資后,將金額隨機分為幾份,然后隨機從借款人表里面選幾個,然后通過一條條select for update 去更新借款人表里面的余額等。
抽象出來就是一個session通過for循環會有幾條如下的語句:
Select * from xxx where id='隨機id' for update
基本來說,程序開啟后不一會就死鎖。
這可以是說最經典的死鎖情形了。
例如兩個用戶同時投資,A用戶金額隨機分為2份,分給借款人1,2
B用戶金額隨機分為2份,分給借款人2,1
由于加鎖的順序不一樣,死鎖當然很快就出現了。
對于這個問題的改進很簡單,直接把所有分配到的借款人直接一次鎖住就行了。
Select
* from xxx where id in (xx,xx,xx) for update
在in里面的列表值mysql是會自動從小到大排序,加鎖也是一條條從小到大加的鎖
例如(以下會話id為主鍵):
Session1:
mysql> select * from t3 where id in (8,9) for update;
+----+--------+------+---------------------+
| id | course | name | ctime |
+----+--------+------+---------------------+
| 8 | WA | f | 2016-03-02 11:36:30 |
| 9 | JX | f | 2016-03-01 11:36:30 |
+----+--------+------+---------------------+
2 rows in set (0.04 sec)
Session2:
select * from t3 where id in (10,8,5) for update;
鎖等待中……
其實這個時候id=10這條記錄沒有被鎖住的,但id=5的記錄已經被鎖住了,鎖的等待在id=8的這里。
不信請看
Session3:
mysql> select * from t3 where id=5 for update;
鎖等待中
Session4:
mysql> select * from t3 where id=10 for update;
+----+--------+------+---------------------+
| id | course | name | ctime |
+----+--------+------+---------------------+
| 10 | JB | g | 2016-03-10 11:45:05 |
+----+--------+------+---------------------+
1 row in set (0.00 sec)
在其它session中id=5是加不了鎖的,但是id=10是可以加上鎖的。
案例2:
在開發中,經常會做這類的判斷需求:根據字段值查詢(有索引),如果不存在,則插入;否則更新。
以id為主鍵為例,目前還沒有id=22的行
Session1:
select * from t3 where id=22 for update;
Empty set (0.00 sec)
session2:
select * from t3 where id=23 for update;
Empty set (0.00 sec)
Session1:
insert into t3 values(22,'ac','a',now());
鎖等待中……
Session2:
insert into t3 values(23,'bc','b',now());
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
當對存在的行進行鎖的時候(主鍵),mysql就只有行鎖。
當對未存在的行進行鎖的時候(即使條件為主鍵),mysql是會鎖住一段范圍(有gap鎖)
鎖住的范圍為:
(無窮小或小于表中鎖住id的最大值,無窮大或大于表中鎖住id的最小值)
如:如果表中目前有已有的id為(11 , 12)
那么就鎖住(12,無窮大)
如果表中目前已有的id為(11 , 30)
那么就鎖住(11,30)
對于這種死鎖的解決辦法是:
insert into t3(xx,xx) on duplicate key update `xx`='XX';
用mysql特有的語法來解決此問題。因為insert語句對于主鍵來說,插入的行不管有沒有存在,都會只有行鎖。
案例3:
直接上情景:
mysql> select * from t3 where id=9 for update;
+----+--------+------+---------------------+
| id | course | name | ctime |
+----+--------+------+---------------------+
| 9 | JX | f | 2016-03-01 11:36:30 |
+----+--------+------+---------------------+
1 row in set (0.00 sec)
Session2:
mysql> select * from t3 where id<20 for update;
鎖等待中
Session1:
mysql> insert into t3 values(7,'ae','a',now());
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
這個跟案例一其它是差不多的情況,只是session1不按常理出牌了,
Session2在等待Session1的id=9的鎖,session2又持了1到8的鎖(注意9到19的范圍并沒有被session2鎖住),最后,session1在插入新行時又得等待session2,故死鎖發生了。
這種一般是在業務需求中基本不會出現,因為你鎖住了id=9,卻又想插入id=7的行,這就有點跳了,當然肯定也有解決的方法,那就是重理業務需求,避免這樣的寫法。
附記,推薦兩篇好文章
案例4:
MySQL 加鎖處理分析:
MySQL學習筆記(五)并發時經典常見的死鎖原因及解決方法
MySQL都有什么鎖? MySQL有三種鎖的級別:頁級.表級.行級. 表級鎖:開銷小,加鎖快:不會出現死鎖:鎖定粒度大,發生鎖沖突的概率最高,并發度最低. 行級鎖:開銷大,加鎖慢:會出現死鎖:鎖定粒度 ...
Java并發編程:Java ConcurrentModificationException異常原因和解決方法
Java ConcurrentModificationException異常原因和解決方法 在前面一篇文章中提到,對Vector.ArrayList在迭代的時候如果同時對其進行修改就會拋出java.u ...
I2C死鎖原因及解決方法(轉)
源:http://blog.csdn.net/zyboy2000/article/details/5603091 死鎖總線表現為:SCL為高,SDA一直為低 現象:單片機采用硬件i2c讀取E2PROM ...
[轉載]常見slave 延遲原因以及解決方法
一 ?序言在運維線上M-M 架構的MySQL數據庫時,接收的比較多關于主備延時的報警: 點擊(此處)折疊或打開 check_ins_slave_lag (err_cnt:1)critical-slav ...
常見slave 延遲原因以及解決方法
一 ?序言在運維線上M-M 架構的MySQL數據庫時,接收的比較多關于主備延時的報警: 點擊(此處)折疊或打開 check_ins_slave_lag (err_cnt:1)critical-slav ...
sqlserver 死鎖原因及解決方法
其實所有的死鎖最深層的原因就是一個:資源競爭 表現一: 一個用戶A 訪問表A(鎖住了表A),然后又訪問表B,另一個用戶B 訪問表B(鎖住了表B),然后企圖訪問表A,這時用戶A由于用戶B已經鎖住表B,它 ...
mysql 報Row size too large 65535 原因與解決方法
報錯信息:Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535 ...
C++(八)— 死鎖原因及解決方法
1.死鎖原因 死鎖問題被認為是線程/進程間切換消耗系統性能的一種極端情況.在死鎖時,線程/進程間相互等待資源,而又不釋放自身的資源,導致無窮無盡的等待,其結果是任務永遠無法執行完成. 打個比方,假設有 ...
一些常見warning的原因和解決方法
在入職三周后,終于趕齊了接手項目落下兩個月的項目,有了一些自己的空閑時間對項目進行整理.主要整理包括類目的整合,從原來一個系統文件夾下幾百個文件整改為以MVC設計思想為原則的分文件夾整理類目,井然有序 ...
隨機推薦
查看SQLServer最耗資源時間的SQL語句
執行最慢的SQL語句 SELECT (total_elapsed_time / execution_count)/1000 N'平均時間ms' ,total_elapsed_time/1000 N'總 ...
226 Invert Binary Tree
/** * Definition for a binary tree node. * function TreeNode(val) { * this.val = val; * this.left = ...
6款基于SVG的HTML5應用和動畫
1.HTML5 SVG 3D蝴蝶飛舞動畫 逼真超酷 這次我們要分享的這款HTML5動畫簡直就是逆天,利用SVG制作的3D蝴蝶飛舞動畫,蝴蝶飛舞動畫非常逼真,蝴蝶飛舞的路線是利用SVG構造的.另外,動畫 ...
php之Cookie與Session詳解
Cookie管理 Cookie是在HTTP協議下,通過服務器或腳本語言可以維護客戶瀏覽器上信息的一種方式,Cookie的使用很普遍,許多提供個人化服務的網站都是利用Cookie來區別不同用戶,以顯示與 ...
五年級--python函數高級運用
一.裝飾器 二.迭代器 三.生成器 四.練習 一.裝飾器 1.1 閉包函數用法 # 需求: # 執行一個函數前需要認證是否登錄,如果登錄則不需再登錄. # 只認證一次,后續操作無需認證 # 要求認證使 ...
Vue2.x源碼學習筆記-從一個小例子查看vm實例生命周期
學習任何一門框架,都不可能一股腦兒的從入口代碼從上到下,把代碼看完, 這樣其實是很枯燥的,我想也很少有人這么干,或者這么干著干著可能干不下去了. 因為肯定很無聊. 我們先從一個最最簡單的小例子,來查看 ...
java課程課后作業05之動手動腦
一.使用Files. walkFileTree()找出指定文件夾下所有大于指定大小(比如1M)的文件 此代碼沒有使用walkfiletree,兩者的差別在于walkfiletree在遍歷文件的時候有一 ...
Linux之因BASH造成的鍵盤錯誤和環境問題
對于Linux我們習慣使用/bin/bash.并且大多數人操作在Centos系統上,但是仍有不少人在ubuntu上使用,兩個操作系統大同小異.都是使用了Linux內核.接下來就來講講我使用過程中兩個系 ...
linux操作系統4 軟件包管理
知識內容: 1.軟件包介紹 2.基本軟件包安裝 3.yum軟件包管理 4.apt軟件包管理 5.源碼安裝 一.軟件包介紹 1.軟件包分類 壓縮包形式:類似.tar.gz結尾的文件(源碼) rpm: r ...
javascript 判斷空數組
javascript里判斷空數組不能用 []==[] 這樣來判斷,因為數組也是個對象,普通對象通過指針指向的內存中的地址來做比較 所以 []==[]結果為false,因此判斷數組是否為空 用 [].l ...
總結
以上是生活随笔為你收集整理的mysql 死锁原因_Mysql并发时经典常见的死锁原因及解决方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql float 精度阶段_mys
- 下一篇: mysql隔离级别 简书_数据库事务和四