session 1:
mysql> begin;
query ok, 0 rows affected (0.00 sec)
mysql> delete from test where table_name=』columns』;
query ok, 256 rows affected (0.07 sec)
session 2:
mysql> begin
-> ;
query ok, 0 rows affected (0.00 sec)
mysql> delete from test where table_name=』collations』;
error 1205 (hy000): lock wait timeout exceeded; try restarting transaction
mysql> insert into test select * from test where table_name=』collations』;
query ok, 256 rows affected (0.05 sec)
records: 256 duplicates: 0 warnings: 0
mysql> delete from test where table_name=』collations』;
error 1205 (hy000): lock wait timeout exceeded; try restarting transaction
mysql> begin;
query ok, 0 rows affected (0.00 sec)
mysql> insert into test select * from test where table_name=』collations』;
query ok, 512 rows affected (0.07 sec)
records: 512 duplicates: 0 warnings: 0
我們看到,session2的delete語句是刪除不同的行,但是被阻塞了,session2中的insert是沒有受影響的,這個時候其實新增的並不是表鎖,是對所有的記錄加了x記錄鎖。下面的檢視可以看出是x的record鎖
mysql> select * from information_schema.innodb_locks\g
*****************1. row*****************
lock_id: 17968:179:3:3
lock_trx_id: 17968
lock_mode: x
lock_type: record
lock_table:test
.test
lock_index: gen_clust_index
lock_space: 179
lock_page: 3
lock_rec: 3
lock_data: 0x0000008f4103
*****************2. row*****************
lock_id: 17967:179:3:3
lock_trx_id: 17967
lock_mode: x
lock_type: record
lock_table:test
.test
lock_index: gen_clust_index
lock_space: 179
lock_page: 3
lock_rec: 3
lock_data: 0x0000008f4103
2 rows in set (0.00 sec)
但是在session2中執行update其他記錄的語句,反而沒有被阻塞,在何登成的部落格中提到了「若id列上沒有索引,sql會走聚簇索引的全掃瞄進行過濾,由於過濾是由mysql server層面進行的。因此每條記錄,無論是否滿足條件,都會被加上x鎖。但是,為了效率考量,mysql做了優化,對於不滿足條件的記錄,會在判斷後放鎖,最終持有的,是滿足條件的記錄上的鎖,但是不滿足條件的記錄上的加鎖/放鎖動作不會省略。同時,優化也違背了2pl的約束。」
看來mysql的優化也是分了不同型別的語句處理的。
何登成部落格的相關連線:
MySQL中RR級別下的MVCC
眾所周知mysql中innodb的可重複讀是通過mvcc實現的。mvcc是由哪些元素構成?mvcc的讀 又叫快照讀,在mysql中不可能把整個表的資料拷貝乙份來提供這個快照。它通過 1 undolog innodb增刪資料時除了redo log外還會記錄undo log。以update舉例 undo...
InnoDB在MySQL預設隔離級別下解決幻讀
在rr的隔離級別下,innodb使用mvvc和next key locks解決幻讀,mvvc解決的是普通讀 快照讀 的幻讀,next key locks解決的是當前讀情況下的幻讀。事務a,先執行 update table set name hh where id 3 結果為 ok row xx 表名...
MySQL中的事務隔離級別
sql 標準用三個必須在並行的事務之間避免的現象定義了四個級別的事務隔離。這些不希望發生的現象是 乙個事務讀取了另乙個未提交的並行事務寫的資料。乙個事務重新讀取前面讀取過的資料,發現該資料已經被另乙個已提交的事務修改過。乙個事務重新執行乙個查詢,返回一套符合查詢條件的行,發現這些行因為其他最近提交的...