myisam 儲存引擎使用的鎖定機制完全是由 mysql 提供的表級鎖定實現。
mysql的表級鎖定主要有兩種:寫鎖和讀鎖
對write寫鎖,mysql使用的表鎖定方法原理如下:
* 如果在表上沒有鎖,在它上面放乙個寫鎖。
* 否則,把鎖定請求放在寫鎖定佇列中。
對read讀鎖,mysql使用的表鎖定方法原理如下:
* 如果在表上沒有寫鎖定,把乙個讀鎖定放在它上面。
* 否則,把鎖請求放在讀鎖定佇列中。
當乙個鎖定被釋放時,鎖定可被寫鎖定佇列中的執行緒得到,然後是讀鎖定佇列中的執行緒。這意味著,如果你在乙個表上有許多更新,select語句將等待直到沒有更多的更新。
可以通過檢查table_locks_waited和table_locks_immediate狀態變數來分析系統上的表鎖定爭奪:
mysql> show status like 'table%';
+-----------------------+-------+
| variable_name | value |
+-----------------------+-------+
| table_locks_immediate | 18 |
| table_locks_waited | 0 |
+-----------------------+-------+
如果table_locks_waited的值比較高,則說明存在著較嚴重的表級鎖爭用情況。
在 mysql 中,主要通過四個佇列來維護這兩種鎖定:兩個存放當前正在鎖定中的讀和寫鎖定資訊,另外兩個存放等待中的讀寫鎖定資訊,如下:
• current read-lock queue (lock->read)
• pending read-lock queue (lock->read_wait)
• current write-lock queue (lock->write)
• pending write-lock queue (lock->write_wait)
當客戶端請求寫鎖時,mysql首先檢查在current write-lock queue是否已經有鎖定相同資源到資訊存在,如果current write-lock queue沒有,則再檢查pending write-lock queue ,如果在pending write-lock queue 中找到了,則自己也需要進入該等待佇列;反之,如果在pending write-lock queue 找不到,則再檢測current read-lock queue,如果有鎖定存在,則同樣需要進入pending write-lock queue。如果一開始就檢測到current write-lock queue中有鎖定相同資源的寫鎖存在,那麼就直接進入pending write-lock queue。
讀請求和寫等待佇列中的寫鎖請求的優先順序規則主要為以下規則決定:
1. 除了 read_high_priority 的讀鎖定之外,pending write-lock queue 中的 write 寫鎖定能夠阻塞所有其他的讀鎖定;
2. read_high_priority 讀鎖定的請求能夠阻塞所有 pending write-lock queue 中的寫鎖定;
3. 除了 write 寫鎖定之外,pending write-lock queue 中的其他任何寫鎖定都比讀鎖定的優先順序低。
表級鎖在下列幾種情況下比行級鎖更優越:
1. 很多操作都是讀表。
2. 在嚴格條件的索引上讀取和更新,當更新或者刪除可以用單獨的索引來讀取得到時:
3. update tbl_name set column=value where unique_key_col=key_value;
4. delete from tbl_name where unique_key_col=key_value;
5. select 和 insert 語句併發的執行,但是只有很少的 update 和 delete 語句。
6. 很多的掃瞄表和對全表的 group by 操作,但是沒有任何寫表。
測試:
session a
顯示地給t1表加讀鎖定
mysql> lock table t1 read;
query ok, 0 rows affected (0.00 sec)
自己的讀操作未被阻塞:
mysql> select * from t1;
+------+
| i |
+------+
| 1 |
| 2 |
| 5 |
+------+
3 rows in set (0.00 se)
session b
其他程序的讀操作也未被阻塞:
mysql> select * from t1;
+------+
| i |
+------+
| 1 |
| 2 |
| 5 |
+------+
3 rows in set (0.00 sec)
session a
mysql> update t1 set i=3 limit 1;
error 1099 (hy000): table 't1' was locked with a read lock and can't be updated
session b
mysql> update t1 set i=3 limit 1;
直接被阻塞了
session a
解除讀鎖
mysql> unlock tables;
query ok, 0 rows affected (0.00 sec)
session b
在session a釋放鎖定資源後,session b獲得了資源,更新成功
mysql> update t1 set i=3 limit 1;
query ok, 1 row affected (0.00 sec)
rows matched: 1 changed: 1 warnings: 0
session a
獲取讀鎖的時候增加local選項
mysql> lock table t1 read local;
query ok, 0 rows affected (0.00 sec)
session b
其他session的insert 未被阻塞
mysql> insert into t1 values(6);
query ok, 1 row affected (0.00 sec)
然而,其他session的update被阻塞了
mysql> update t1 set i=3 limit 1;
直接被阻塞鳥
session a
這次加寫鎖
mysql> unlock tables;
query ok, 0 rows affected (0.00 sec)
mysql> lock table t1 write;
query ok, 0 rows affected (0.00 sec)
自己的session可以繼續讀:
mysql> select * from t1;
+------+
| i |
+------+
| 3 |
| 2 |
| 5 |
| 6 |
+------+
4 rows in set (0.00 sec)
session b:
其他session的讀被阻塞了
mysql> select * from t1;
直接被阻塞鳥
session a
釋放鎖定資源
mysql> unlock tables;
query ok, 0 rows affected (0.00 sec)
session b
其他session可以獲得資源了
mysql> select * from t1;
+------+
| i |
+------+
| 3 |
| 2 |
| 5 |
| 6 |
+------+
4 rows in set (0.00 sec)
session a
通過ddl獲取write_allow_read型別的寫鎖定
mysql> alter table t1 add constraint t1_pk primary key(i);
query ok, 4 rows affected (0.07 sec)
records: 4 duplicates: 0 warnings: 0
session b
其他session的讀未被阻塞
mysql> select * from t1;
+---+
| i |
+---+
| 2 |
| 3 |
| 5 |
| 6 |
+---+
4 rows in set (0.00 sec)
理解mysql鎖(2)表級鎖定
理解mysql鎖 2 表級鎖定 myisam 儲存引擎使用的鎖定機制完全是由 mysql 提供的表級鎖定實現。mysql的表級鎖定主要有兩種 寫鎖和讀鎖 對write寫鎖,mysql使用的表鎖定方法原理如下 如果在表上沒有鎖,在它上面放乙個寫鎖。否則,把鎖定請求放在寫鎖定佇列中。對read讀鎖,my...
mysql鎖定某個庫 mysql 表鎖定,庫鎖定
今天在解決資料庫同步異常的時候用到了flush tables with read lock 這個命令,於是順便就學習了下鎖表的相關知識。1.flush tables with read lock 這個命令是全域性讀鎖定,執行了命令之後所有庫所有表都被鎖定唯讀。一般都是用在資料庫聯機備份,這個時候資料...
MySQL行級鎖 表級鎖
行級鎖 表級鎖的資料不能被其它事務再鎖定,也不被其它事務修改 修改 刪除 是表級鎖時,不管是否查詢到記錄,都會鎖定表 innodb 行鎖是通過給索引上的索引項加鎖 來實現的,這一點mysql與 oracle 不同,後者是通過在資料塊中對相應資料行加鎖來實現的。innodb這種行鎖實現特點意味著 只有...