欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Mysql中的Innodb事務(wù)和鎖詳解

 更新時間:2023年09月11日 11:01:07   作者:feiyingHiei  
這篇文章主要介紹了Mysql中的Innodb事務(wù)和鎖詳解,InnoDB是MySQL的一種存儲引擎,它是一種可靠性和性能非常好的存儲引擎,它具有ACID事務(wù)支持,可以提供高并發(fā)性和數(shù)據(jù)完整性,需要的朋友可以參考下

Innodb事務(wù)和鎖

一. 事務(wù)隔離級別

  1. READ UNCOMMITED :讀未提交,事務(wù)之間可以看到彼此之間正在修改的內(nèi)容,會出現(xiàn)所謂的臟讀現(xiàn)象
  2. READ COMMITED : 讀已提交,只能讀取已經(jīng)提交的事務(wù)修改的數(shù)據(jù),不會出現(xiàn)臟讀的現(xiàn)象,但會出現(xiàn)不可重復(fù)讀和幻讀的情況
  3. REPEATABLE READ : 可重復(fù)度,在innodb中解決了不可重復(fù)讀和幻讀的問題
  4. SERIALIZED : 串行化, 這個使用的比較少,隔離性最強,性能也最差

二. 鎖類型

  • S LOCK : 共享鎖 : S鎖與S鎖相互兼容,與X鎖不兼容
  • X LOCK :排他鎖 :與其他所有鎖類型不兼容,簡單的可以理解為讀寫鎖即可
  • 意向鎖 (IS, IX) : 主要是用來表達(dá)加鎖的一種層次概念,比如希望在行級別加X鎖,那么就需要在表級和頁級別加上IX鎖,意向鎖整體上兼容性會比較好,如果當(dāng)前表中已經(jīng)有了多個行級鎖,如果希望嘗試加表鎖,如果沒有意向鎖的話,那么就需要取檢測當(dāng)前行鎖的加鎖情況,但是有了意向鎖,就可以快速判斷當(dāng)前嘗試加表鎖可能是需要等待的。

監(jiān)控方法

  • SHOW ENGINE INNODB STATUS 命令查看innodb引擎信息,其中包含當(dāng)前執(zhí)行事務(wù)的狀態(tài)和鎖的狀態(tài)
  • 通過information_schema提供的表來排查可能存在的問題
    • a. information_schema.innodb_trx
    • b. information_schema.innodb_locks
    • c. innodb_lock_waits

三.鎖釋放的時機

lock通常在事務(wù)commit或是rollback之后才會釋放

四. 一致性非鎖定讀

這是非常常見的問題,事務(wù)中會有大量的select操作,select操作通常情況下是不會對數(shù)據(jù)做加鎖操作的, 這樣保證了數(shù)據(jù)的并發(fā)性能,在不同的事務(wù)隔離級別下,非一致性鎖定讀的行為是不太一樣的

  • READ COMMITED : 讀取undo_log中該行最新的一條快照數(shù)據(jù)
  • READ REPETABLE : 讀取undo_log中,最近的早于當(dāng)前事務(wù)開啟時間的快照數(shù)據(jù)

五. 加鎖算法

上文描述了鎖的類型,即排它鎖,共享鎖,意向鎖之類,這里所說的是加鎖的算法,即為innodb使用了什么樣的加鎖策略來處理實際場景中的并發(fā)問題。

  • record lock : 行鎖,對單個行記錄進行加鎖,行是innodb的最小數(shù)據(jù)管理單位,innodb中有專門的數(shù)據(jù)結(jié)構(gòu)來存儲和管理行記錄,我們所有的查詢的數(shù)據(jù)最終都會落到存儲引擎的行上
  • gap lock : 間隙鎖,即對間隙加鎖,間隙其實就這里只是針對間隙,不包括行(todo ,間隙的概念需要搞一下)
  • next-key lock : 對行和間隙和行都進行加鎖

netx-key lock算法主要解決的問題就是幻讀問題,因此這個算法只在 RR事務(wù)隔離級別中會使用

疑問? 不是MVCC可以在無鎖的情況下解決幻讀的問題嗎,為什么還要上next-key lock這么重的算法呢?這里就要引出兩個概念了,一致性非鎖定讀(快照讀) 和一致性鎖定讀(當(dāng)前讀) 的概念了

一致性非鎖定讀 : 我們平時使用的select * from table 這種查詢語句,都是快照讀,在innodb RC和RR級別下都是通過MVCC機制來實現(xiàn)的,過程中是不加鎖的,讀取的數(shù)據(jù)未必是當(dāng)前行中的真實的數(shù)據(jù)。

一致性鎖定讀 : select * from table for update 或者select * from table in shared mode 在這種情況下RC基本是會對對應(yīng)的行加鎖,RR級別下就會使用next-key算法加鎖。

六、redo日志

redo日志是物理日志,記錄的頁的物理修改日志

七、undo日志

undo日志是邏輯日志,記錄的是操作的sql邏輯,通常我們在修改數(shù)據(jù)的時候,先對行加鎖,然后將該版本的數(shù)據(jù)拷貝到undo日志中,然后修改當(dāng)前行的操作事務(wù)id,修改該行事務(wù),然后把回滾指針指向und日志。

七、MVCC

多版本控制(MVCC)在許多關(guān)系型數(shù)據(jù)庫中都有實現(xiàn),innodb中主要是依賴undo日志來實現(xiàn),其中涉及到的一個比較重要的概念就是read veiw

  • low_limit_id :最大活躍事務(wù)id
  • up_limit_id : 最小活躍事務(wù)id
  • trx_ids : 活躍事務(wù)集合
  • 如果當(dāng)前trx_id > low_limit_id,那數(shù)據(jù)一定是不可見的,因為數(shù)據(jù)是在當(dāng)前事務(wù)開啟后才修改的
  • 如果當(dāng)前trx_id < up_limit_id,那么數(shù)據(jù)一定是可見的,因為事務(wù)在當(dāng)前事務(wù)開啟前就已經(jīng)提交了
  • 如果trx_id 在這之間,那么如果trx_id在trx_ids中,說明事務(wù)還沒有提交,那么數(shù)據(jù)就不可見, 否則事務(wù)就是可見的。

無論是在什么事務(wù)隔離級別下,基于read view的快照讀機制都相同的,只是創(chuàng)建read view的機制不太一樣。

在RR基本下,read view在事務(wù)開啟的時候就創(chuàng)建完成了,二在RC級別下,每次查詢都會重新創(chuàng)建read view。

如果一個當(dāng)前事務(wù)為事務(wù)A, 另外一個事務(wù)是事務(wù)B, 如果事務(wù)A開啟的時候,事務(wù)B已經(jīng)提交了,那么無論在RR級別或是RC級別下,B提交的數(shù)據(jù)對于事務(wù)A都是可見的; 如果B事務(wù)在A事務(wù)開啟之前就已經(jīng)開啟了,但是A啟動的時候B事務(wù)還沒有提交,那么先讓無論RR級別還是RC級別,數(shù)據(jù)在快照讀模式下也都是不可見的;如果B事務(wù)在A開啟之前就開啟,但是在A事務(wù)提交前B事務(wù)就提交了,此時對于RR級別而言,B的trx_id在trx_ids之中(trx_ids是在開啟事務(wù)的時候就已經(jīng)初始化了),那么RR級別下數(shù)據(jù)是可見的,但對于RC而言,重新生成的read view了,顯然數(shù)據(jù)就是可見的。

通過上述的分析,通過mvcc可以在RR級別下快照讀是完全解決了重復(fù)讀和幻讀的問題,RC級別還是會有不可重復(fù)讀和幻讀的問題,但是需要注意的是,MVCC只工作在快照讀(一致性非鎖定讀)條件下,對于當(dāng)前讀的問題是無法走到MVCC的,所以一定要注意,MVCC只解決了快照讀的幻讀和不可重復(fù)讀問題。

這里需要補充一個case來理解一下快照讀與當(dāng)前讀的巨大區(qū)別

CREATE TABLE `user_info` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(10) NOT NULL DEFAULT '',
  `age` int(10) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
)
事務(wù)隔離級別為RR

初始化數(shù)據(jù)

insert into user_info ('name', 'age') values ('jack', 1);

T1時刻A開啟事務(wù),然后啟用快照讀

select * from user_info where id = 1;

查詢到的結(jié)果是

+----+------+-----+
| id | name | age |
+----+------+-----+
|  1 | tom  |   0 |
+----+------+-----+

T2時刻我們開啟事務(wù)B, 并且執(zhí)行

update user_info set age =1 where id = 1;

此時事務(wù)A中執(zhí)行當(dāng)前讀

select * from user_info where id = 1 for update;

事務(wù)A將會被阻塞 此時提交事務(wù)B,事務(wù)A中顯示的查詢結(jié)果為

+----+------+-----+
| id | name | age |
+----+------+-----+
|  1 | tom  |   1 |
+----+------+-----+

然后我們再次執(zhí)行一次快照讀

select * from user_info where id = 1;

獲得的結(jié)果為

+----+------+-----+
| id | name | age |
+----+------+-----+
|  1 | tom  |   0 |
+----+------+-----+

通過上述的例子,可以看到,快照讀和當(dāng)前讀有著非常大的區(qū)別,在同一個事務(wù)當(dāng)中,快照讀和當(dāng)前讀返回的結(jié)果有可能是不一樣的。

我們看到,mvcc保證了快照讀每次讀取的數(shù)據(jù)是一致,next-key算法保證了當(dāng)前讀是一致。

到此這篇關(guān)于Mysql中的Innodb事務(wù)和鎖詳解的文章就介紹到這了,更多相關(guān)Innodb事務(wù)和鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論