前言:鎖是計算機協調多個進程或線程並發訪問某一資源的機制。在數據庫中,除傳統的計算機資源(如CPU、RAM、I/O等)的爭用外,數據也是一種供許多用戶共享的資源。如何保證數據並發訪問的一致性、有效性是所有數據庫必須解決的一個問題,鎖沖突也是影響數據並發訪問性能的一個重要因素。從這個角度來說,鎖對數據庫而言顯得尤其重要,也更加復雜。
1.鎖的分類
#1.從對數據操作的類型來分
讀鎖(共享鎖)和寫鎖(排它鎖)
#2.從對數據操作的粒度來分
表鎖和行鎖
2.表鎖(偏讀)
特點:偏向MyISAM存儲引擎,開銷小,加鎖快,無死鎖,鎖定粒度大,發生鎖沖突的概率最高,並發度低。下面通過案例來說明表鎖的一些情況。
#1.創建mylock表,並插入5條數據。注意數據引擎使用的是MyISAM。
drop table if exists mylock; CREATE TABLE mylock ( id INT PRIMARY KEY auto_increment, name VARCHAR (20) NOT NULL ) ENGINE MyISAM DEFAULT charset = utf8; insert into mylock (name) values ('a'); insert into mylock (name) values ('b'); insert into mylock (name) values ('c'); insert into mylock (name) values ('d'); insert into mylock (name) values ('e');
#2.手動增加表鎖命令。
lock table tablename1 read(write),tablename2 read(write);
#3.查看表是否被加鎖。
如果In_use顯示不為0,則表示表被加鎖。
#4.釋放表鎖命令
unlock tables;
3.表鎖(read)案例
#1.在mylock表上加讀鎖。將當前會話命名為A。
在A會話中查詢mylock中的數據。
數據查詢正常,沒有任何問題。
#2.再開一個會話,命名為B,查詢mylock中的數據。
數據查詢正常,沒有任何問題。
#3.進行其他操作。
①在A會話中進行更新操作。
分析:
提示mylock表被加鎖,不能進行更新操作。原因:mylock正被讀鎖鎖住,未解鎖不能進行更新操作。
②在B會話中讀其他表。
分析:
A會話mylock表的讀鎖,並不影響B會話對mylock表和其他表的讀操作。
③在A會話中讀其他表。
分析:
由於A會話對mylock表加了讀鎖,在未解鎖前,不能操作其他表。
④在B會話中修改mylock表中的內容。
分析:
出現了阻塞情況,原因:由於A會話對mylock表加鎖,在鎖未釋放時,其他會話是不能對mylock表進行更新操作的。
⑤在A會話中對mylock表進行解鎖操作,注意觀察B會話中的變化。
分析:
在A會話中對mylock表解鎖后,B會話更新操作成功,可看到B會話中的更新操作等待了22分鍾。
4.表鎖(write)案例
#1.在A會話中對mylock表加寫鎖。
#2.在A會話中對mylock表進行讀寫操作。
分析:
由於A會話對mylock表加的寫鎖,所以讀寫操作都執行正常。
#3.在A會話中對其他表進行操作。
分析:
在A會話中對其他表進行讀寫操作都失敗,因為A會話中mylock表的寫鎖並未被釋放。
#4.在B會話中對mylock表進行讀操作。
分析:
由於mylock表已經加寫鎖,而寫鎖為排它鎖,因此在B會話中對mylock表進行讀操作阻塞。
由於B會話中對mylock的讀操作都阻塞,所以其他操作也是阻塞的。
5.表鎖定分析
#1.使用如下命令查看是否有表被鎖定。
show open tables where In_use>0;
#2.使用如下命令分析表鎖。
show status like 'table%';
主要注意兩個變量的值:
①Table_locks_immediate:產生表級鎖定的次數,表示可立即獲取鎖的查詢次數,每立即獲取鎖一次該值加1。
②Table_locks_waited:出現表級鎖定爭用而發生等待的次數(不能立即獲取鎖的次數,每等待一次鎖該值加1),此值高則說明存在較嚴重的表級鎖爭用情況。
總結
注意數據庫引擎為MyISAM。
①對MyISAM表加讀鎖,不會阻塞其他進程對同一表(mylock)的讀操作,但是會阻塞對同一表的寫請求,只有當讀鎖釋放后,才會執行其他進程的寫操作。
②在加讀鎖並未釋放鎖時,該進程不能對同一表(mylock)進行寫操作,並且也不能對其他表進行操作。
③對MyISAM表加寫鎖,會阻塞其他進程對同一表(mylock)的讀和寫操作,只有當寫鎖釋放后,才會執行其他進程的寫操作。
④在加寫鎖並未釋放鎖時,該進程不能對其他表進行操作。
簡而言之:讀鎖會阻塞寫,但是不會阻塞讀,而寫鎖會把讀和寫都阻塞。
此外,MyISAM的讀寫鎖調度是寫優先,這也是MyISAM不適合做寫為主的表的引擎,因為寫鎖后,其他線程不能做任何操作,大量的更新會使查詢很難得到鎖,從而造成長時間阻塞。
by Shawn Chen,2018.6.28日,上午。