關於不同隔離級別下對鎖機制的影響

衆所周之,隔離級別分爲:

  1.       Read Uncommited:可以讀取提交的記錄

  2.      ReadCommitted:僅讀到提交的數據,會產生幻讀現象

  3.     Repeatable Read :對讀取到的數據加鎖,並對讀取的範圍加鎖,不存在幻讀現象

  4.     Serializable:讀加讀鎖寫加寫鎖,串行執行

 

情況一:主鍵(where  主鍵=???)

 

Read Committed隔離級別

 

show create table key_id;

+--------+----------------------------------------------------------------------------------------------------------------------------------------------------------+

| Table | Create Table                                                                                                                                            |

+--------+----------------------------------------------------------------------------------------------------------------------------------------------------------+

| key_id | CREATE TABLE `key_id` (

 `id` char(128) NOT NULL DEFAULT '',

 `data` char(128) DEFAULT NULL,

 PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 |

 

 

 

mysql> select * from key_id;

+----+------+

| id | data |

+----+------+

| 10 | bb  |

| 2 | b    |

| 3 | c    |

| 4 | a    |

| 8 | cd   |

+----+------+

 

第一個事務

start transaction ;

Query OK, 0 rows affected (0.00 sec)

 

mysql> delete from key_id where id=’3’

   -> ;

Query OK, 1 row affected (0.00 sec)

 

第二個事務

update key_id set data='cc' where id=’3’;

ERROR 1205 (HY000): Lock wait timeoutexceeded; try restarting transaction

update key_id set data='cc' where id=’4’;

Query OK, 1 row affected (0.01 sec)

Id=3key鎖住了,其他的列可以更新。

#####記錄行鎖

 

Repeatable Read 隔離級別

事務1

mysql> start transaction ;

Query OK, 0 rows affected (0.00 sec)

 

mysql> update key_id set data='kl' whereid='8';

Query OK, 1 row affected (0.00 sec)

Rows matched: 1  Changed: 1 Warnings: 0

 

事務2

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)

 

mysql> update key_id set data='kk' whereid='4';

Query OK, 1 row affected (0.00 sec)

Rows matched: 1  Changed: 1 Warnings: 0

 

mysql> delete from key_id where id='4';

Query OK, 1 row affected (0.00 sec)

 

mysql> delete from key_id where id='8';

^CCtrl-C -- sending "KILL QUERY63" to server ...

Ctrl-C -- query aborted.

ERROR 1317 (70100): Query execution wasinterrupted

mysql> insert into no_index values('15','b');

ERROR 1136 (21S01): Column count doesn'tmatch value count at row 1

mysql> insert into key_id values('15','b');

Query OK, 1 row affected (0.00 sec)

 

#####說明where  主鍵=???或者是Insert,是行鎖,RepeatableReadRead Committed沒有區別,並且同一事務內操作不會互鎖。

 

 

 

 

 

情況二:沒有索引

CREATE TABLE `no_index` (

 `id` int(11) DEFAULT NULL,

 `fir` varchar(128) DEFAULT NULL,

 `sec` varchar(128) DEFAULT NULL

)

 

mysql> select * from no_index;

+------+------+------+

| id  | fir  | sec  |

+------+------+------+

|   1 |  a   | aa  |

|   2 |  b   | bb  |

|   3 | c    | cc   |

+------+------+------+

 

 

Read Committed

事務1

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)

 

mysql> delete from  no_index where id=1;

 

事務2 delete其他行被鎖住

mysql> start transaction;

mysql> delete from no_index where id=3;

Ctrl-C -- sending "KILL QUERY707" to server ...

Ctrl-C -- query aborted.

 

事務1

 

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)

 

mysql> delete from  no_index where id=1;

事務2 updateinsert其他行沒有被鎖

mysql> update no_index set id=30  where id=3;

Query OK, 1 row affected (0.02 sec)

Rows matched: 1  Changed: 1 Warnings: 0

mysql> insert into no_index values('12','a','b');

Query OK, 1 row affected (0.00 sec)

#####在無索引情況下updateinsertdeleteRepeatable Read)是全表鎖。然而當其他事務運用update,insert操作時,會觸發semi-consistent產生優化,全表鎖降爲行鎖,其他事務運用delete操作仍然被全表鎖。

 

Repeatable Read 隔離級別

 

事務1

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)

mysql> update no_index set id=10where id=1;

 

事務2updateinsertdelete操作都被鎖住

mysql> insert into no_index values('14','a','b');

Ctrl-C -- sending "KILL QUERY707" to server ...

Ctrl-C -- query aborted.

ERROR 1317 (70100): Query execution wasinterrupted

mysql> delete from no_index whereid=3;

Ctrl-C -- sending "KILL QUERY707" to server ...

Ctrl-C -- query aborted.

ERROR 1317 (70100): Query execution wasinterrupted

mysql> update no_index set id=30  where id=3;

Ctrl-C -- sending "KILL QUERY707" to server ...

Ctrl-C -- query aborted.

ERROR 1317 (70100): Query execution wasinterrupted

 

 

######可以看到在無索引情況下Repeatable Read是全表鎖,其他事務運用update,insert操作時不觸及優化。

 

 

第三情況:普通索引(where  索引=???)

CREATE TABLE `index_id` (

 `id` int(11) DEFAULT NULL,

 `fir` varchar(128) DEFAULT NULL,

 `sec` varchar(128) DEFAULT NULL,

  KEY`id` (`id`)

)

 

READ-COMMITTED

事務1

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)

mysql> delete from  index_id where id=1;

Query OK, 1 row affected (0.00 sec)

事務2

mysql> start transaction;

 

Query OK, 0 rows affected (0.00 sec)

mysql> update index_id set id=1  where id=3;

Query OK, 1 row affected (0.00 sec)

Rows matched: 1  Changed: 1 Warnings: 0

#####READ-COMMITTED說明where  索引=???或者是Insert時,是行鎖。

 

repeatable-read

事務1

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)

mysql> delete from  index_id where id=1;

Query OK, 1 row affected (0.01 sec)

 

事務2 id不能更新爲1,因爲事務1id=1是更新行,id=1有間隙鎖。更新爲其他數字則不受影響

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)

mysql> update index_id set id=10  where id=3;

Query OK, 1 row affected (0.00 sec)

Rows matched: 1  Changed: 1 Warnings: 0

mysql> update index_id set id=1  where id=3;

Ctrl-C -- sending "KILL QUERY715" to server ...

Ctrl-C -- query aborted.

ERROR 1317 (70100): Query execution wasinterrupted

 

#####可以看到repeatable-read下事務1刪除id這行時,產生行鎖外還產生間隙鎖,使得被更新的這條記錄不會產生幻讀現象。那爲什麼在無索引或者唯一索引時不會有間隙鎖的產生?是因爲唯一索引時保證了被更新的那條記錄只有一條不會產生幻讀。無索引情況下,整個表已經被全部鎖住了,所以不會產生幻讀現象


總結:在Read Committed下,即使不用索引,其他事務使用update,insert其他行不會鎖等待。在repeatable-read下,運用普通索引做DML操作時會增加間隙鎖(爲了保證不會幻讀),即其他數據不能改爲被索引的那個行的那個列的值。如:事務1 update a set id=2 where id=1,事務2 update a set id=1 where id=10; 事務2 間隙鎖造成id改爲1不被允許。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章