Mysql事務和鎖

Mysql事務

這裏主要講的是Mysql InnoDB引擎相關事務和鎖。Mysql事務主要和上訴數據庫理論中相似,有所不一樣的是在事務隔離級別的Repeatable Read(可重複讀)、和鎖有着不一樣的實現。html

事務隔離級別

Mysql一樣有4種事務隔離級別,其中Repeatable Read(可重複讀)是Mysql默認隔離級別,其經過MVCC機制實現了不會出現幻讀現象。mysql

隔離級別 髒讀 不可重複讀 幻讀
Read Uncommitted 可能 可能 可能
Read Committed 不能 可能 可能
Repeatable Read 不能 不能 不能
Serializable 不能 不能 不能

Mysql能夠經過下訴API操做事務隔離級別:sql

查看系統隔離級別:
select @@global.tx_isolation;
查看當前會話隔離級別
select @@tx_isolation;
設置當前會話隔離級別
SET session TRANSACTION ISOLATION LEVEL serializable;
設置全局系統隔離級別
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

Mysql鎖

Mysql InnoDB引擎有悲觀鎖、樂觀鎖(MVCC),其共同組成Mysql相關鎖機制,而且Mysql經過其使用Repeatable Read可以防止幻讀的出現。數據庫

Mysql悲觀鎖

Mysql主要有下面4種悲觀鎖:網絡

  • 共享鎖(S鎖、多鎖): 事務得到元組的共享鎖後,其它事務也只能得到該元組的共享鎖,而不能得到排它鎖;得到共享鎖的事務能夠對元組進行讀操做。
  • 排它鎖(X鎖,寫鎖): 事務得到元組的排它鎖後,其它事務既不能得到該元組的共享鎖,也不能得到排它鎖;得到排它鎖的事務能夠對元組進行寫操做。
  • 意向共享鎖(IS鎖): 事務打算給數據行加行共享鎖,事務在給一個數據行加共享鎖前必須先取得該表的IS鎖。
  • 意向排它鎖(IX鎖): 事務打算給數據行加行排他鎖,事務在給一個數據行加排他鎖前必須先取得該表的IX鎖。

IS、S、IX、X鎖的兼容性爲:session

圖片來自網絡

Mysql InnoDB引擎默認支持行鎖,來儘可能縮小鎖定元組的粒度,行鎖分爲三級,粒度從小到大依次是:mvc

  • 記錄鎖(Record Lock):單行
  • 間隔鎖(Gap Lock):一個開區間內的多行
  • 防插入鎖(Next-Key Lock):一個前開後閉區間內的多行,其實是記錄鎖和間隔鎖的結合

Mysql樂觀鎖(MVCC)

前面所說,樂觀鎖機制經過在表中添加version字段進行實現。在Mysql InnoDB引擎中,其會在每行數據中額外添加兩個隱藏值來實現MVCC,這兩個值一個記錄這行數據什麼時候被建立,另一個記錄這行數據什麼時候更新(或者被刪除)。在實際操做中,每開啓一個新事務,事務的版本號就會遞增。.net

Mysql事務隔離級別和其對應鎖級別

Read Uncommited

任何操做都不加鎖code

Read Commited

操做 鎖對應級別
select * 無鎖
select * for update 排它鎖
select * lock in share mode 共享鎖
insert 排它鎖,行鎖中的記錄鎖
delete 排它鎖,行鎖中的記錄鎖
update 排它鎖,行鎖中的記錄鎖

Repeated Read

操做 鎖對應級別
select * 樂觀鎖(MVCC機制),也叫快照讀(snapshot read)
select * for update 排它鎖
select * lock in share mode 共享鎖
insert 排它鎖,行鎖中的記錄鎖
delete 排它鎖,行鎖中的防插入鎖
update 排它鎖,行鎖中的防插入鎖

Serializable

該隔離級別下,讀(select)下會加共享鎖,至關於select lock in share mode,寫會加排他鎖,讀寫互斥,至關於所有使用悲觀鎖實現事務隔離級別。htm

Mysql解決Repeatable Read事務隔離級別的可重複讀和幻讀問題

Mysql在Repeatable Read事務隔離級別下,經過MVCC機制、update和delete操做的防插入鎖解決可重複讀和幻讀問題。

可重複讀問題

這裏主要由Mysql的MVCC機制所解決的。mysql會在每行數據中額外添加什麼時候被建立什麼時候被更新兩個版本號字段,在RP級別下,每一個操做對應得MVCC版本號字段的操做:

  • select: 讀取建立版本號<=當前版本號,更新版本號爲空或<=當前版本號
  • insert: 保存當前事務版本號爲行的建立版本號
  • update: 保存當前事務版本號爲行建立版本號,同時保存當前事務版本號到行更新版本號
  • delete: 保存當前事務版本號爲行的更新版本號

因此咱們由上可知在事務A在select操做時,事務B的update和delete操做並不會影響事務A的select操做。

幻讀問題

幻讀問題咱們主要是因爲insert操做致使,因此這裏面主要涉及到select時有insert操做和update(delete)時有insert操做,下面主要講這兩種Mysql InnoDB引擎是如何解決的。

select時的insert操做

由上所訴解決可重複讀問題,該操做已由Mysql的MVCC機制所解決

update和delete時的insert操做

該操做主要由Mysql InnoDB引擎的防插入鎖(Next-Key Lock)解決的。防插入鎖的區間是根據索引來肯定的。對於沒有索引的列會直接鎖表。下面是一個例子:

--------------------------------------------------------------------------------------------------
事務A                                              |                       事務B
--------------------------------------------------------------------------------------------------
begin                                              |                       begin
--------------------------------------------------------------------------------------------------
update isolation set name = '-2' where name = '2'; |
--------------------------------------------------------------------------------------------------
                                                   |      insert into isolation(name) values('2');
                                                   |      // 這裏會阻塞等待
--------------------------------------------------------------------------------------------------------
commit                                             |                       
--------------------------------------------------------------------------------------------------------

注意:上面事務A的update操做會形成name='2'的行鎖和name=(-∞, 2]和[2, +∞)的間隔鎖,其統稱爲防插入鎖。

Reference

https://tech.meituan.com/innodb-lock.html http://chenzhou123520.iteye.com/blog/1860954 https://blog.csdn.net/sadfishsc/article/details/51027734

相關文章
相關標籤/搜索