其實,看到“死鎖”二字,不需要王二,就是我,來再廢口舌,這兩個字名如其意,已經可以透過現象看本質了。不過呢,我雖然長著一副程序猿的樣子,但一直沒有理解好mysql的死鎖概念,為此還曾苦惱過,覺得自己有愧於程序猿的臉面。有幸第N次拜讀《高性能mysql》,恍惚間覺得自己明白了一些,也就是有點對得起程序猿這三個字了。
死鎖是指兩個或者多個事務在同一資源上相互占用,並請求鎖定對方占用的資源,從而導致惡性循環的現象。
看看人家說得多好,可我王二愣是不能夠發自於肺腑的理解,在這條路上走了很多彎路。
回到洛陽後,我一直做的是大宗期貨交易項目,既然是交易,肯定涉及到數據的多並發,大宗期貨交易的模式很復雜,說實話,我維護了整個項目的正常運作,但對於“買漲”、“買跌”都有可能賺錢的路數,還是不清楚,只能怪自己太遲鈍。所以只好舉個簡單的例子了。
我有兩個好朋友,一個叫王一,一個叫王三,一個芳齡十八(本來想年方二八呢,一想這年齡好像未成年,覺得不合適),一個芳齡29,一個如花似玉,一個風韻猶存。王二,也就是我,作為一個屌絲男,能夠交到這兩個異性朋友,真是托了程序員的福。
那天王一很苦惱,她不知道怎麼把win7操作系統升級到win10,小青年都挺喜歡接受新東西,於是找到了我,丟給我一句:“猿兄,幫我忙呗,升級個操作系統!”“當然好啊,大哥我巴不得啊”,我心裡這樣想,但是強裝淡定,於是回了句“恩,稍等,哥忙著呢。”不過最終我成功幫她升級了操作系統,這妹的,崇拜我得不行,於是就成為了朋友。 關於王三,算了,我再這麼無恥的yy下去,你肯定要來打醒我了,就這樣吧。
場景就是,算了,還是上sql吧,我y不下去了。
START TRANSACTION;
update girl SET age=18 where id=2;
update girl set age=29 where id=1;
COMMIT;
START TRANSACTION;
UPDATE girl set age=19 where id=1;
update girl set age=30 where id=2;
commit;
如果湊巧,兩個事務都執行了第一條update語句,分別修改了王一和王三的年紀,同時也鎖定了改行語句,接著,每個事務都嘗試執行第二條語句時,卻發現該行已被對方鎖定,然後兩個事務都在等待對方釋放鎖,同時又持有對方需要的鎖,則陷入死循環。
也就是說,逝水流年,王一和王三也逃不過時光的蹉跎,然而,在我心中,也就是王二的心中,卻永遠都不想他們老去,於是我和時光老人就干上了架,這會發生什麼呢?
等待結局
時光老人
王二
[SQL]START TRANSACTION;
受影響的行: 0
時間: 0.000s
[SQL]UPDATE girl set age=19 where id=1;
受影響的行: 0
時間: 0.001s
[SQL]START TRANSACTION;
受影響的行: 0
時間: 0.000s
[SQL]update girl SET age=18 where id=2;
受影響的行: 1
時間: 0.001s
[SQL]update girl set age=30 where id=2;
[SQL]update girl set age=29 where id=1;
[Err] 1213 - Deadlock found when trying to get lock; try restarting transaction
innodb存儲引擎,能檢測到死鎖的循環依賴,並立即返回一個錯誤。
好吧,我還是干不過時光老人!
假如這樣呢
故事到這裡肯定是沒有結束啊,我得想想辦法,避免和時光老人發生沖突,於是就這樣吧!
START TRANSACTION;
UPDATE girl set age=19 where id=1;
update girl set age=30 where id=2;
commit;
START TRANSACTION;
update girl SET age=18 where id=1;
update girl set age=29 where id=2;
COMMIT;
也就是說,在實戰當中,假如我們遇到類似的問題,雖然innodb為我們做了錯誤的檢測,但是我們還是要避免死鎖的。
時光老人
王二
[SQL]START TRANSACTION;
受影響的行: 0
時間: 0.037s
[SQL]
UPDATE girl set age=19 where id=1;
受影響的行: 0
時間: 0.001s
[SQL]START TRANSACTION;
受影響的行: 0
時間: 0.001s
[SQL]
update girl SET age=18 where id=1;
也就是說,在有這樣的update時,盡量按照順序來執行,避免沖突。當然了,情況不同,你如果不想這樣,那就請不要相信我的鬼話,哈哈哈!
好了,好了,mysql之死鎖就這樣結束吧!