1. 程式人生 > >行鎖和表鎖的理解

行鎖和表鎖的理解

在mysql 的 InnoDB引擎支援行鎖,與Oracle不同,mysql的行鎖是通過索引載入的,即是行鎖是加在索引響應的行上的,要是對應的SQL語句沒有走索引,則會全表掃描

表鎖:不會出現死鎖,發生鎖衝突機率高,併發低。
行鎖:會出現死鎖,發生鎖衝突機率低,併發高。

鎖衝突:例如說事務A將某幾行上鎖後,事務B又對其上鎖,鎖不能共存否則會出現鎖衝突。(但是共享鎖可以共存,共享鎖和排它鎖不能共存,排它鎖和排它鎖也不可以)

死鎖:例如說兩個事務,事務A鎖住了15行,同時事務B鎖住了610行,此時事務A請求鎖住610行,就會阻塞直到事務B施放610行的鎖,而隨後事務B又請求鎖住15行,事務B也阻塞直到事務A釋放1

5行的鎖。死鎖發生時,會產生Deadlock錯誤。

鎖是對錶操作的,所以自然鎖住全表的表鎖就不會出現死鎖。
行鎖:
共享鎖又稱:讀鎖。當一個事務對某幾行上讀鎖時,允許其他事務對這幾行進行讀操作,但不允許其進行寫操作,也不允許其他事務給這幾行上寫鎖。(讀寫鎖不能共存,讀的時候不能讓其它事務進行寫操作,更不能上寫鎖,如果其其它事務對同一行上讀鎖的話會造成該事務的阻塞)。
排它鎖又稱:寫鎖。當一個事務對某幾行上寫鎖時,不允許其他事務寫,但允許讀(如果讀也就是查,不上讀鎖可能是髒讀,上讀鎖之後等待對應事務提交或者回滾後方可讀到實時資料)。更不允許其他事務給這幾行上任何鎖(讀鎖會阻塞)。包括寫鎖。

上共享鎖的寫法:lock in share mode(讀)例如: select math from zje where math>60 lock in share mode;
上排它鎖的寫法:for update(寫) 例如:select math from zje where math >60 for update;

注意幾點:
1.行鎖必須有索引才能實現,否則會自動鎖全表,那麼就不是行鎖了。
2.兩個事務不能鎖同一個索引(不能有鎖住有交集的行)
如下:
事務A先執行:
select math from zje where math>60 for update;
事務B再執行:
select math from zje where math<60 for update;
這樣的話,事務B是會阻塞的。如果事務B把 math索引換成其他索引就不會阻塞,但注意,換成其他索引鎖住的行不能和math索引鎖住的行有重複

insert ,delete , update在事務中都會自動預設加上排它鎖(寫)。
會話1:select math from zje where math>60 for update;
會話2:update zje set math=99 where math=68;阻塞…
如上,會話1先把zje表中math>60的行上排它鎖。然後會話2試圖把math=68的行進行修改,math=68處於math>60中,所以是已經被鎖的,會話2進行操作時,
就會阻塞,等待會話1把鎖釋放。當commit時或者程式結束時,會釋放鎖。