<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
MySQL 有三種鎖的級別:頁級、表級、行級
1 表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖衝突的概率最高, 並行度最低。
2 行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的概率最低, 並行度也最高。
3 頁面鎖:開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,並行度一般。
所謂死鎖 <DeadLock>
:是指兩個或兩個以上的程序在執行過程中, 因爭奪資源而造成的一種互相等待的現象, 若無外力作用,它們都將無法推進下去. 此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的程序稱為死鎖程序。表級鎖不會產生死鎖. 所以解決死鎖主要還是針對於最常用的 InnoDB。
死鎖的關鍵在於:兩個 (或以上) 的 Session 加鎖的順序不一致。
那麼對應的解決死鎖問題的關鍵就是:讓不同的 session 加鎖有次序。
需求:將投資的錢拆成幾份隨機分配給借款人。
起初業務程式思路是這樣的:
投資人投資後,將金額隨機分為幾份,然後隨機從借款人表裡面選幾個,然後通過一條條 select 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 | +----+--------+------+---------------------+ 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 | +----+--------+------+---------------------+ row in set (0.00 sec)
在其它 session 中 id=5 是加不了鎖的,但是 id=10 是可以加上鎖的。
在開發中,經常會做這類的判斷需求:根據欄位值查詢(有索引),如果不存在,則插入;否則更新。
以 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 語句對於主鍵來說,插入的行不管有沒有存在,都會只有行鎖。
mysql> select * from t3 where id=9 for update; +----+--------+------+---------------------+ | id | course | name | ctime | +----+--------+------+---------------------+ | 9 | JX | f | 2016-03-01 11:36:30 | +----+--------+------+---------------------+ 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 的行,這就有點跳了,當然肯定也有解決的方法,那就是重理業務需求,避免這樣的寫法。
一般的情況,兩個 session 分別通過一個 sql 持有一把鎖,然後互相存取對方加鎖的資料產生死鎖。
兩個單條的 sql 語句涉及到的加鎖資料相同,但是加鎖順序不同,導致了死鎖。
CREATE TABLE dltask ( id bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', a varchar(30) NOT NULL COMMENT 'uniq.a', b varchar(30) NOT NULL COMMENT 'uniq.b', c varchar(30) NOT NULL COMMENT 'uniq.c', x varchar(30) NOT NULL COMMENT 'data', PRIMARY KEY (id), UNIQUE KEY uniq_a_b_c (a, b, c) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='deadlock test';
a,b,c 三列,組合成一個唯一索引,主鍵索引為 id 列。
事務隔離級別:RR (Repeatable Read)
每個事務只有一條 SQL:
delete from dltask where a=? and b=? and c=?;
到此這篇關於MySQL產生死鎖原因分析講解的文章就介紹到這了,更多相關MySQL死鎖內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45