MySQL性能優化(八)-- 鎖機制之表鎖

數據庫的鎖主要用來保證數據的一致性的。MyISAM存儲引擎只支持表鎖,InnoDB存儲引擎既支持行鎖,也支持表鎖,但默認狀況下是採用行鎖。mysql

1、鎖分類

1.按照對數據操做的類型分:讀鎖,寫鎖sql

  • 讀鎖:也稱爲共享鎖。 針對同一資源,多個併發讀操做能夠並行執行,而且互不影響,可是不能寫
  • 寫鎖:也稱排它鎖。當前線程寫數據的時候,會阻塞其它線程來讀取數據 或者 寫數據

注:讀鎖和寫鎖都是阻塞鎖。數據庫

2.按照數據操做的粒度:表鎖,行鎖,頁鎖bash

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

2、加鎖與解鎖

1.手動增長表鎖併發

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

2.解鎖ui

unlock tables;spa

3.查看哪些表被鎖線程

show open tables;3d

3、表鎖案例

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

4、MyISAM存儲引擎中鎖特色

  • 執行select語句的時候,會自動給涉及的表加上表鎖,在執行更新操做時,會自動給表加上寫鎖
  • MyISAM存儲引擎比較適合做爲以查詢爲主的表存儲引擎,不適合寫爲主的表存儲引擎,由於加寫鎖後,是鎖住整個表,其餘用戶線程不能作任何操做,這樣會致使大量用戶線程阻塞的狀況。

5、表鎖的狀態查詢

1.查詢指令

show status like 'table_lock%';

img

說明:

  • Table_locks_immediate:表示能夠當即獲取鎖的查詢次數,每獲取一次鎖就增長1
  • Table_locks_waited:鎖等待的次數(重要,若是這個值的大,則說明鎖表的次數多,須要優化,經過 show open tables,查看哪些表鎖了,而後分析爲何會鎖)。

歡迎關注個人公衆號,第一時間接收最新文章~ 搜索公衆號: 碼咖 或者 掃描下方二維碼:

img
相關文章
相關標籤/搜索