MySQL -- 表鎖

翻身碼農把歌唱發表於2018-07-24

前言

資料庫的鎖主要用來保證資料的一致性的。MyISAM儲存引擎只支援表鎖,InnoDB儲存引擎既支援行鎖,也支援表鎖,但預設情況下是採用行鎖。

一、鎖分類

1.按照對資料操作的型別分:讀鎖,寫鎖

  • 讀鎖:也稱為共享鎖。 針對同一資源,多個併發讀操作可以並行執行,並且互不影響,但是不能寫
  • 寫鎖:也稱排它鎖。當前執行緒寫資料的時候,會阻塞其它執行緒來讀取資料 或者 寫資料

注:讀鎖和寫鎖都是阻塞鎖。

2.按照資料操作的粒度:表鎖,行鎖,頁鎖

  • 表鎖:開銷小,加鎖快,主要在myisam儲存引擎中出現。特點:鎖住整個表,開銷小,加鎖快,無死鎖情況, 鎖的粒度大,在併發情況下,產生鎖等待的概率比較高,所以說,支援的併發數比較低,一般用於查詢
  • 行鎖:開銷大,加鎖慢,鎖定單獨的某個表中的某一行記錄,主要用於innodb儲存引擎。特點:有死鎖情況,鎖定粒度最小,發生鎖衝突的概率最低,支援的併發數也最高
  • 頁鎖:開銷和加鎖時間界於表鎖和行鎖之間。會出現死鎖,鎖定粒度界於表鎖和行鎖之間,併發度一般

二、加鎖與解鎖

1.手動增加表鎖

lock table 表名 [read|write],表名 [read|write]…

2.解鎖

unlock tables;

3.檢視哪些表被鎖

show open tables;

三、表鎖案例

1.讀鎖
create table lock_one(
    id int primary key auto_increment,
   col int
)engine=myisam;

insert into lock_one(col) values (1);
insert into lock_one(col) values (2);
insert into lock_one(col) values (3);
複製程式碼

下面我們模擬兩個使用者,即兩個執行緒連線資料庫,開啟兩個xsheel視窗,連線到mysql:

  1. 在會話1中對lock_one表增加讀鎖

lock table lock_one read;

  1. 在當前會話(會話1)中是否可以select該表呢,也就是說對 lock_one增加了讀鎖後,在當前會話中是否可以讀呢?

select * from lock_one;

答案是可以的。

  1. 在另一個會話中(會話2)是否可以select該表呢?

答案也是可以的。

  1. 那麼在會話1中是否可以查詢其他表呢?

例如,查詢 users表:select * from users;

img

我們發現是不可以查詢其他表的,這是因為當前會話已經對lock_one表加上了鎖,即當前執行緒鎖住了lock_one表,只可以操作lock_one表,就不可以查詢其他的表。

  1. 問題來了,會話2是否可以查詢其他表呢?

select * from users;

img

我們發現是可以的。因為會話2和會話1是沒有關係的,會話2查詢會話1鎖住的表都可以,查詢沒有鎖住的 肯定是可以的。

  1. 在會話1中是否可以更新(增刪改)鎖住的lock_one表呢?

update lock_one set col=66 where id=1;

img

發現是不可以的,因為我們對 lock_one表加了 讀鎖,所以是不可以 進行寫操作的。

  1. 在會話2中是否可以更新(增刪改)會話1中鎖住的lock_one表呢?

img

我們發現是沒有執行結果的,也就是說 正在等待更新,在阻塞等待中。因為我們在會話1中對lock_one中增加了讀鎖,其他人只有讀的操作,沒有寫的操作。

  1. 在會話1中 對lock_one進行解鎖時,會話2中的更新(增刪改)操作 就會立即執行。

img

2.寫鎖
  1. 在會話1中對lock_one表增加寫鎖

lock table lock_one write;

  1. 在會話1中查詢該表

select * from lock_one;

我們發現是可以的。

  1. 在會話2中查詢該表

img

我們發現是沒有執行結果的,也就是說 處於阻塞狀態。因為寫鎖是排它鎖,其他使用者執行緒不可以讀取當前鎖住的表,只有解鎖之後 其他使用者執行緒才可以執行select

img

  1. 在會話1中對lock_one進行寫鎖後,會話1會否可以查詢其他表呢?

select * from users;

img

我們發現是不可以的。道理和讀鎖的時候一樣,當前會話已經對lock_one表加上了鎖,即當前執行緒鎖住了lock_one表,只可以操作lock_one表,就不可以查詢其他的表。

  1. 那麼在會話2中是否可以查詢其他表呢?

答案肯定是可以的。因為之和鎖的表有關係,和其他表沒有任何關係。

  1. 在會話1中是否可以進行寫(增刪改)操作呢?

答案一定是可以的。因為會話1對lock_one表進行了寫鎖操作,也就是隻可以寫。

  1. 在會話2中是否可以進行寫(增刪改)操作呢?

img

我們發現是不可以的。因為寫鎖是排它鎖,也就是隻可以當前執行緒操作鎖住的表,其他使用者執行緒需要等到解鎖之後才可以操作該表。

img

3.總結
  1. 甲對錶A加了讀鎖
  • 甲對錶A可以執行讀(查詢)操作,但不可以執行寫(增刪改)操作
  • 甲對其他表不可以執行讀寫(增刪改查)操作
  • 乙對錶A可以執行讀(查詢)操作,但不可以執行寫(增刪改)操作
  • 乙對其他表可以執行讀寫(增刪改查)操作  
    img
  1. 甲對錶A加了寫鎖
  • 甲對錶A可以執行讀寫(增刪改查)操作
  • 甲對其他表不可以執行讀寫(增刪改查)操作
  • 乙對錶A不可以執行讀寫(增刪改查)操作
  • 乙對其他表可以執行讀寫(增刪改查)操作  
    img

四、MyISAM儲存引擎中鎖特點

1.執行select語句的時候,會自動給涉及的表加上表鎖,在執行更新操作時,會自動給表加上寫鎖

2.MyISAM儲存引擎比較適合作為以查詢為主的表儲存引擎,不適合寫為主的表儲存引擎,因為加寫鎖後,是鎖住整個表,其他使用者執行緒不能做任何操作,

這樣會導致大量使用者執行緒阻塞的情況。

五、表鎖的狀態查詢

查詢指令:show status like 'table_lock%';

img
說明:

Table_locks_immediate:表示可以立即獲取鎖的查詢次數,每獲取一次鎖就增加1

Table_locks_waited:鎖等待的次數(重要,如果這個值的大,則說明鎖表的次數多,需要優化,通過 show open tables,檢視哪些表鎖了,然後分析為什麼會鎖)。

歡迎關注我的公眾號哦~ 搜尋公眾號:翻身碼農把歌唱 或者 掃描下方二維碼:

img

相關文章