MySQL鎖的用法之表級鎖

鎖機制是數(shù)據(jù)庫有別于文件系統(tǒng)的一個重要的特點,也是用來管理并發(fā)訪問的一個有效的方式。mysql的鎖分為表級鎖、頁級鎖與行級鎖。表級鎖是MySQL中粒度最大的一種鎖,它實現(xiàn)簡單,資源消耗較少,被大部分MySQL引擎支持。最常使用的MYISAM與INNODB都支持表級鎖

鎖機制是數(shù)據(jù)庫有別于文件系統(tǒng)的一個重要的特點,也是用來管理并發(fā)訪問的一個有效的方式。MySQL的鎖分為表級鎖、頁級鎖與行級鎖。表級鎖是MySQL中粒度最大的一種鎖,它實現(xiàn)簡單,資源消耗較少,被大部分MySQL引擎支持。最常使用的MYISAM與INNODB都支持表級鎖定。
??? 表級鎖定分為兩類,讀鎖與寫鎖。讀鎖是預(yù)期將對數(shù)據(jù)表進行讀取操作,鎖定期間保證表不能被修改。寫鎖是預(yù)期會對數(shù)據(jù)表更新操作,鎖定期間保證表不能被其他線程更新或讀取。

??? 讀鎖:

??? 用法: LOCK TABLE table_name [ AS alias_name ] READ

??? 指定數(shù)據(jù)表,LOCK類型為READ即可,AS別名是可選參數(shù),如果指定別名,使用時也要指定別名才可

??? 申請讀鎖前提:當(dāng)前沒有線程對該數(shù)據(jù)表使用寫鎖,否則申請會阻塞。

??? 操作限制:其他線程可以對鎖定表使用讀鎖;其他線程不可以對鎖定表使用寫鎖

? 寫操作 讀操作
使用讀鎖線程 否(報錯) 能
不使用讀鎖線程 否(阻塞) 能
??? 對于使用讀鎖的MySQL線程,由于讀鎖不允許任何線程對鎖定表進行修改,在釋放鎖資源前,該線程對表操作只能進行讀操作,寫操作時會提示非法操作。而對于其他沒使用鎖的MySQL線程,對鎖定表進行讀操作可以正常進行,但是進行寫操作時,線程會等待讀鎖的釋放,當(dāng)鎖定表的所有讀鎖都釋放時,線程才會響應(yīng)寫操作。

? 寫鎖:

??? 用法: LOCK TABLE table_name [AS alias_name] [ LOW_PRIORITY ] WRITE

??? 別名用法與讀鎖一樣,寫鎖增加了指定優(yōu)先級的功能,加入LOW_PRIORITY可以指定寫鎖為低優(yōu)先級。

??? 申請寫鎖前提: 當(dāng)沒有線程對該數(shù)據(jù)表使用寫鎖與讀鎖,否則申請回阻塞。

??? 操作限制:其他MySQL線程不可以對鎖表使用寫鎖、讀鎖
? 寫操作 讀操作
使用寫鎖線程 能 能
不使用寫鎖線程 否(阻塞) 能(阻塞)
??? 對于使用寫鎖的MySQL線程,其可以對鎖定表進行讀寫操作。但是對于其他線程,對指定表讀寫操作都是非法的,需要等待直到寫鎖釋放。

鎖分配優(yōu)先級:

對于鎖分配的優(yōu)先級,是: LOW_PRIORITY WRITE
1. 當(dāng)多個線程申請鎖,會優(yōu)先分配給WRITE鎖,不存在WRITE鎖時,才分配READ鎖,LOW_PRIORITY WRITE需要等到WRITE鎖與READ都釋放后,才有機會分配到資源。

2. 對于相同優(yōu)先級的鎖申請,分配原則為誰先申請,誰先分配。

注意事項:

1. 不能操作(查詢或更新)沒有被鎖定的表。

??? 例如當(dāng)只申請table1的讀鎖,SQL語句中包含對table2的操作是非法的。例如:

mysql> LOCK TABLE test READ;?
Query OK, 0 rows affected (0.00 sec)?
?
mysql> SELECT * FROM test_myisam;?
ERROR 1100 (HY000): Table ‘test_myisam’ was not locked with LOCK TABLES?
2. 不能在一個SQL中使用兩次表(除非使用別名)

??? 當(dāng)SQL語句中多次使用一張表時,系統(tǒng)會報錯。例如:

mysql> LOCK TABLE test READ;?
Query OK, 0 rows affected (0.00 sec)?
?
mysql> SELECT * FROM test WHERE id IN (SELECT id FROM test );?
ERROR 1100 (HY000): Table ‘test’ was not locked with LOCK TABLES?
解決這個問題的方法是使用別名,如果多次使用到一個表,需要聲明多個別名。
mysql> LOCK TABLE test AS t1 READ, test AS t2 READ;?
Query OK, 0 rows affected (0.00 sec)?
?
mysql>? SELECT * FROM test AS t1 WHERE id IN (SELECT id FROM test AS t2);?
+—-+———–+??
| id | content?? |?
+—-+———–+??
|? 1 | tt_1????? |?
|? 3 | new_3???? |?
|? 4 | new_4???? |?
|? 5 | content_5 |?
+—-+———–+??
4 rows in set (0.00 sec)?
3.? 申請鎖時使用別名,使用鎖定表時必須加上別名。

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊14 分享