文章目錄
- mysql事務原理MVCC
- 1存盤引擎
- 1.InnoDB存盤引擎
- 2.MyISAM存盤引擎
- 2.undo和redo的功能
- undo:
- redo:
- 3.mysql鎖
- 3.1表級鎖
- 3.2行級鎖
- 3.3全域鎖
- 3.4避免阻塞與死鎖
- 阻塞:食堂排隊
- 3.5.mysql死鎖
- 不同表
- 同一個表
- 避免死鎖
- 4.MVCC多版本并發控制
- mvcc如何解決隔離性
- 隱式欄位
- Read View
- 讀已提交RC read-commited
- 解決不可重復讀RR read-repeatable
- 解決不了幻讀
- 5.總結
mysql事務原理MVCC
書籍推薦:mysql必知必會
? 深入淺出mysql
? mysql高性能(偏DBA)
資料量較小:索引(一個庫)
資料量較大:分庫分表,讀寫分離
mysql優化是一個大的范圍,需要豐富的經驗,課程中會把作為一個java程式員(非DBA)基本的、常用的一一列舉出來,希望大家盡可能多的掌握,因為太多了,而我們重點在java,所以每個知識點都只會抽取重點來學習,如果以后大家專案中需要這方面的,大家以這個為基礎,再去深入學習,也是沒有問題的,
select * from xxx where id=1

①建立連接1.1(Connectors&Connection Pool),通過客戶端/服務器通信協議與MySQL建立連
接,MySQL 客戶端與服務端的通信方式是 “ 半雙工 ”,對于每一個 MySQL 的連接,時刻都有一個
執行緒狀態來標識這個連接正在做什么,
通訊機制:
全雙工:能同時發送和接收資料,例如平時打電話,
半雙工:指的某一時刻,要么發送資料,要么接收資料,不能同時,例如早期對講機
單工:只能發送資料或只能接收資料,例如單行道
執行緒狀態:系統故障
show processlist; //查看用戶正在運行的執行緒資訊,root用戶能查看所有執行緒,其他用戶只能看自
己的
id:執行緒ID,可以使用kill xx;
user:啟動這個執行緒的用戶
Host:發送請求的客戶端的IP和埠號
db:當前命令在哪個庫執行
Command:該執行緒正在執行的操作命令
Create DB:正在創建庫操作
Drop DB:正在洗掉庫操作
Execute:正在執行一個PreparedStatement
Close Stmt:正在關閉一個PreparedStatement
Query:正在執行一個陳述句
Sleep:正在等待客戶端發送陳述句
Quit:正在退出
Shutdown:正在關閉服務器
Time:表示該執行緒處于當前狀態的時間,單位是秒
State:執行緒狀態
Updating:正在搜索匹配記錄,進行修改
Sleeping:正在等待客戶端發送新請求
Starting:正在執行請求處理
Checking table:正在檢查資料表
Closing table : 正在將表中資料重繪到磁盤中
Locked:被其他查詢鎖住了記錄
Sending Data:正在處理Select查詢,同時將結果發送給客戶端
Info:一般記錄執行緒執行的陳述句,默認顯示前100個字符,想查看完整的使用show full
processlist;
②查詢快取(Cache&Buffer),這是MySQL的一個可優化查詢的地方,如果開啟了查詢快取且在
查詢快取程序中查詢到完全相同的SQL陳述句,則將查詢結果直接回傳給客戶端;如果沒有開啟查詢
快取或者沒有查詢到完全相同的 SQL 陳述句則會由決議器進行語法語意決議,并生成“決議樹”,
快取Select查詢的結果和SQL陳述句
執行Select查詢時,先查詢快取,判斷是否存在可用的記錄集,要求是否完全相同(包括參
數值),這樣才會匹配快取資料命中,
即使開啟查詢快取,以下SQL也不能快取
查詢陳述句使用SQL_NO_CACHE
查詢的結果大于query_cache_limit設定
查詢中有一些不確定的引數,比如now()
show variables like '%query_cache%'; //查看查詢快取是否啟用,空間大小,限制等
show status like 'Qcache%'; //查看更詳細的快取引數,可用快取空間,快取塊,快取多少等
③決議器(Parser)將客戶端發送的SQL進行語法決議,生成"決議樹",前處理器根據一些MySQL
規則進一步檢查“決議樹”是否合法,例如這里將檢查資料表和資料列是否存在,還會決議名字和別
名,看看它們是否有歧義,最后生成新的“決議樹”,
④查詢優化器(Optimizer)根據“決議樹”生成最優的執行計劃,MySQL使用很多優化策略生成最
優的執行計劃,可以分為兩類:靜態優化(編譯時優化)、動態優化(運行時優化),
等價變換策略
A:5=5 and a>5 改成 a > 5 去除恒成立條件
a < b and a=5 改成b>5 and a=5
基于聯合索引,調整條件位置等
優化count、min、max等函式
InnoDB引擎min函式只需要找索引最左邊
InnoDB引擎max函式只需要找索引最右邊
MyISAM引擎count(*),不需要計算,直接回傳
提前終止查詢
使用了limit查詢,獲取limit所需的資料,就不在繼續遍歷后面資料
in的優化
MySQL對in查詢,會先進行排序,再采用二分法查找資料,比如where id in (2,1,3),變
成 in (1,2,3)
B:join優化:inner join/join 自動優化小表驅動大表,left right沒法優化
select from a join b 10萬個 20萬--40萬
select from b join a 1000個 2000-4000
a表大,b表小,基于主鍵索引,每條資料查詢的IO次數2-4
⑤查詢執行引擎負責執行 SQL 陳述句,此時查詢執行引擎會根據 SQL 陳述句中表的存盤引擎型別,以
及對應的API介面與底層存盤引擎快取或者物理檔案的互動,得到查詢結果并回傳給客戶端,若開
啟用查詢快取,這時會將SQL 陳述句和結果完整地保存到查詢快取(Cache&Buffer)中,以后若有
相同的 SQL 陳述句執行則直接回傳結果,
如果開啟了查詢快取,先將查詢結果做快取操作
回傳結果過多,采用增量模式回傳
1存盤引擎
存盤引擎:
MySQL中的資料用各種不同的技術存盤在檔案(或者記憶體)中,這些技術中的每一種技術都使用不同的存盤機制、索引技巧、鎖定水平并且最終提供廣泛的不同的功能和能力,通過選擇不同的技術,你能夠獲得額外的速度或者功能,從而改善你的應用的整體功能,
? 這些不同的技術以及配套的相關功能在 MySQL中被稱作存盤引擎(也稱作表型別)
因為在關系資料庫中資料的存盤是以表的形式存盤的,所以存盤引擎也可以稱為表型別(Table Type,即存盤和操作此表的型別),
Mysql存盤引擎分類:
MyISAM、InnoDB、MEMORY、MERGE等
CREATE TABLE `brand` (
`id` int(11) NOT NULL AUTO_INCREMENT
) ENGINE=InnoDB DEFAULT CHARSET=utf8; #指定引擎
默認存盤引擎
SHOW ENGINES

1.InnoDB存盤引擎
InnoDB是事務型資料庫的首選引擎,通過上圖也看到了,InnoDB是目前MYSQL的默認事務型引擎,是目前最重要、使用最廣泛的存盤引擎,支持事務安全表(ACID),支持行鎖定和外鍵,InnoDB主要特性有:
1、InnoDB mysql現在默認支持的引擎,每張表的存盤都按主鍵順序存放,如果沒有顯示在表定義時指定主鍵,InnoDB會為每一行生成一個6位元組的隱藏ROWID,并以此作為主鍵
2、支持事務安全表(ACID),支持行鎖定和外鍵
場景:由于其支持事務處理,支持外鍵,支持崩潰修復能力和并發控制,如果需要對事務的完整性要求比較高(比如銀行),要求實作并發控制(比如售票),那選擇InnoDB有很大的優勢,因為支持事務的提交(commit)和回滾(rollback),
總結:(理解并記住)
1.支持事務、支持外鍵
2.支持行級鎖與表級鎖
3.花費資源去處理事務,效率比不上MyISAM
4.有事務日志,恢復資料較方便
5.索引為聚簇索引
雖然InnoDB不斷優化,效率已經有了很大提升,但是還是比不上MyISAM
2.MyISAM存盤引擎
MyISAM基于ISAM存盤引擎,并對其進行擴展,它是在Web、資料倉儲和其他應用環境下最常使用的存盤引擎之一,MyISAM擁有較高的插入、查詢速度,但不支持事物和外鍵,
總結(記住)
Mysql 5.5版本之前的默認的存盤引擎
1.不支持事務、不支持外鍵
2.只支持表級鎖(后面介紹)
3.沒有事務日志,故障恢復資料較麻煩
4.磁區存放檔案,平均分配IO,不用花費資源去處理事務,效率較高
5.索引為非聚簇索引
2.undo和redo的功能
id 1 name 張三
update xxx set name=‘李四’ where id=1
mysql為提高效率,每次修改不會直接修改磁盤,會先修改buffer,然后再由mysql自己的執行緒purge去重繪到磁盤,為了支持回滾,得記錄修改之前得狀態
事務開啟前,先寫undo日志
undo:
保證了事務原子性
資料修改前的內容(用于回滾),當把資料從磁盤讀取記憶體的時候,每次資料操作這些資料都會變臟,就是臟資料,需要都會記錄undo日志,當發生回滾的時候,就需要這些日志用來回滾資料
Undo:意為撤銷或取消,以撤銷操作為目的,回傳指定某個狀態的操作,
Undo Log:資料庫事務開始之前,會將要修改的記錄存放到 Undo 日志里,當事務回滾時或者數
據庫崩潰時,可以利用 Undo 日志,撤銷未提交事務對資料庫產生的影響,
Undo Log產生和銷毀:Undo Log在事務開始前產生;事務在提交時,并不會立刻洗掉undo
log,innodb會將該事務對應的undo log放入到洗掉串列中,后面會通過后臺執行緒purge thread進
行回收處理,Undo Log屬于邏輯日志,記錄一個變化程序,例如執行一個delete,undolog會記
錄一個insert;執行一個update,undolog會記錄一個相反的update,
Undo Log存盤:undo log采用段的方式管理和記錄,在innodb資料檔案中包含一種rollback
segment回滾段,內部包含1024個undo log segment,可以通過下面一組引數來控制Undo log存
儲,
實作事務的原子性
Undo Log 是為了實作事務的原子性而出現的產物,事務處理程序中,如果出現了錯誤或者用戶執
行了 ROLLBACK 陳述句,MySQL 可以利用 Undo Log 中的備份將資料恢復到事務開始之前的狀態,
實作多版本并發控制(MVCC)
Undo Log 在 MySQL InnoDB 存盤引擎中用來實作多版本并發控制,事務未提交之前,Undo Log
保存了未提交之前的版本資料,Undo Log 中的資料可作為資料舊版本快照供其他并發事務進行快
照讀
事務A手動開啟事務,執行更新操作,首先會把更新命中的資料備份到 Undo Buffer 中,
事務B手動開啟事務,執行查詢操作,會讀取 Undo 日志資料回傳,進行快照讀
undo log是用來回滾資料的用于保障 未提交事務的原子性
redo:
資料修改后的內容,在緩沖池,然后資料修改后生成redo日志,需要把這些記憶體中的資料插入到磁盤,這個時候當資料庫宕機的時候,這些redo就是重要的記錄,重啟之后會把redo日志也就是修改的資料重新寫入資料庫,
寫buffer得時候,也會同時寫redo日志,因為寫redo(順序io)日志的速度遠遠高于,寫mysql資料(mysql資料以頁為單位存盤,隨機io)
保證了ACID的持久性
(1)redo log 的存盤是順序存盤,而快取同步是隨機操作,
(2)快取同步是以資料頁為單位的,每次傳輸的資料大小大于redo log,Redo:顧名思義就是重做,以恢復操作為目的,在資料庫發生意外時重現操作,
Redo Log:指事務中修改的任何資料,將最新的資料備份存盤的位置(Redo Log),被稱為重做
日志,
Redo Log 的生成和釋放:隨著事務操作的執行,就會生成Redo Log,在事務提交時會將產生
Redo Log寫入Log Buffer,并不是隨著事務的提交就立刻寫入磁盤檔案,等事務操作的臟頁寫入
到磁盤之后,Redo Log 的使命也就完成了,Redo Log占用的空間就可以重用(被覆寫寫入),
Redo Log作業原理
Redo Log 是為了實作事務的持久性而出現的產物,防止在發生故障的時間點,尚有臟頁未寫入表
的 IBD 檔案中,在重啟 MySQL 服務的時候,根據 Redo Log 進行重做,從而達到事務的未入磁盤
資料進行持久化這一特性
redo log是用來恢復資料的 用于保障,已提交事務的持久化特性
(1)redo log 的存盤是順序存盤,而快取同步是隨機操作,
(2)快取同步是以資料頁為單位的,每次傳輸的資料大小大于redo log,
假設有A、B兩個資料,值分別為1,2.
1. 事務開始
2. 記錄A=1到undo log
3. 修改A=3
4. 記錄A=3到 redo log
5. 記錄B=2到 undo log
6. 修改B=4
7. 記錄B=4到redo log
8. 將redo log寫入磁盤
9. 事務提交
3.mysql鎖
1.增刪改,mysql會默認加寫鎖
2.select * from sing where s_num=‘10001’ lock in share mode;加讀鎖 讀讀可以共享
3.讀寫鎖不共享
4.for update 加的寫鎖
共享鎖與排他鎖
-
共享鎖(讀鎖):其他事務可以讀,但不能寫,
-
排他鎖(寫鎖) :其他事務不能讀取,也不能寫,
MySQL 不同的存盤引擎支持不同的鎖機制,所有的存盤引擎都以自己的方式顯現了鎖機制,服務器層完全不了解存盤引擎中的鎖實作: MyISAM 和 MEMORY 存盤引擎采用的是表級鎖(table-level locking) BDB 存盤引擎采用的是頁面鎖(page-level locking),但也支持表級鎖 InnoDB 存盤引擎既支持行級鎖(row-level locking),也支持表級鎖,但默認情況下是采用行級鎖, 默認情況下,表鎖和行鎖都是自動獲得的, 不需要額外的命令, 但是在有的情況下, 用戶需要明確地進行鎖表或者進行事務的控制, 以便確保整個事務的完整性,這樣就需要使用事務控制和鎖定陳述句來完成,3.1表級鎖
鎖住整張表,開銷小,加鎖快;不會出現死鎖(因為MyISAM會一次性獲得SQL所需的全部鎖);鎖定粒度大,發生鎖沖突的概率最高,并發度最低, 演示:兩個cmd
lock table xxxx write/read
unlock tables

3.2行級鎖
開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖沖突的概率最低,并發度也最高
select xxx for update

3.3全域鎖
全域鎖就是對整個資料庫實體加鎖,MySQL提供了一個加全域讀鎖的方法,命令是Flush tables with read lock,當需要讓整個庫處于只讀狀態的時候,可以使用這個命令,之后其他執行緒的以下陳述句會被阻塞:資料更新陳述句(資料的增刪改)、資料定義陳述句(包括建表、修改表結構等)和更新類事務的提交陳述句
全域鎖的典型使用場景是,做全庫邏輯備份,也就是把整庫每個表都select出來存成文本
但是讓整個庫都只讀,可能出現以下問題:
- 如果在主庫上備份,那么在備份期間都不能執行更新,業務基本上就得停擺
- 如果在從庫上備份,那么在備份期間從庫不能執行主庫同步過來的binlog,會導致主從延遲
3.4避免阻塞與死鎖
阻塞:食堂排隊
1.詳細的分析產品需求 會有哪些查詢,哪些修改,好好建表,減少長事務操作
2.分布式事務中,采用弱一致性,可以減少阻塞
3.最直接最簡單的方法就是把表的資料量變小(針對于資料量確實很大了,分庫分表)
4.當然sql陳述句調優、提高代碼質量等都是很重要的
如果真的出現了:
show full PROCESSLIST:查看狀態,可以參考前面的屬性,必要情況下 直接kill
3.5.mysql死鎖
相互等待對方釋放鎖,形成死鎖
不同表

同一個表

避免死鎖
1.編號解死鎖:對鎖編號,按順序鎖, 比如AB 每個執行緒都做判斷,始終先鎖A 在鎖B
2.首先在innodb搜索引擎中,會根據演算法主動進行部分死鎖的檢測與釋放,比如上面的例子自動釋放,
3.大事務拆小,大事務更傾向于死鎖,大事務鎖的時間長,如果業務允許,將大事務拆小(DBA建表功底),
4.為表添加合理的索引
4.MVCC多版本并發控制
最主要就是解決讀寫互斥,寫時復制讀寫分離,空間換時間
id :1 name 張三
事務1:select * from xxx where id=1 ------>復制在一個地方
事務2:update xxx where id=1 資料庫改
改的地方跟我讀的不是同一個,讀寫分離
MVCC
MVCC,全稱Multi-Version Concurrency Control,即多版本并發控制,MVCC是一種并發控制的方法,一般在資料庫管理系統中,實作對資料庫的并發訪問,在編程語言中實作事務記憶體,什么是當前讀和快照讀?
在學習MVCC多版本并發控制之前,我們必須先了解一下,什么是MySQL InnoDB下的當前讀和快照讀?
-
當前讀
像select lock in share mode(共享鎖), select for update ; update, insert ,delete(排他鎖)這些操作都是一種當前讀,為什么叫當前讀?就是它讀取的是記錄的最新版本,讀取時還要保證其他并發事務不能修改當前記錄,會對讀取的記錄進行加鎖,A事務:select * from xxxx in share mode 當前讀,讀取到資料庫最新資料
? 一系列操作…
? select * from xxxx in share mode 當前讀,讀取到資料庫最新資料
? 因為加鎖,如果沒有鎖,使用當前讀,就會出現不可重復讀,幻讀
-
快照讀
像不加鎖的select操作就是快照讀,即不加鎖的非阻塞讀;快照讀的前提是隔離級別不是串行級別,串行級別下的快照讀會退化成當前讀;之所以出現快照讀的情況,是基于提高并發性能的考慮,快照讀的實作是基于多版本并發控制,即MVCC,可以認為MVCC是行鎖的一個變種,但它在很多情況下,避免了加鎖操作,降低了開銷;既然是基于多版本,即快照讀可能讀到的并不一定是資料的最新版本,而有可能是之前的歷史版本A事務:select * from xxxx 把當前這個時刻的記錄照個相,在記憶體中就是復制了一份資料
? 一系列操作,,,,操作的程序中有可能其它事務已經更改了資料
? select * from xxxx 這次讀取不會讀到其它事務修改資料,因為在一個事務中如果沒有觸發當前讀,那 么就只會有一次快照讀
? 所以mvcc的快照讀就在不加鎖的鎖 的情況下解決了不可重復讀,既然沒有加鎖,那么這邊查詢,其它事務就可以更改,于是解決讀寫沖突
資料庫并發場景有三種,分別為:(針對沒有措施的情況下)
-
讀-讀:不存在任何問題,也不需要并發控制
-
讀-寫:有執行緒安全問題,可能會造成事務隔離性問題,可能遇到臟讀,幻讀,不可重復讀
-
寫-寫:有執行緒安全問題,可能會存在更新丟失問題,比如第一類更新丟失,第二類更新丟失
第一類更新丟失:
A事務撤銷了B事務操作

第二類更新丟失
A事務覆寫B事務已經提交的資料,造成B事務所做操作丟失

mvcc如何解決隔離性
隱式欄位
每行記錄除了我們自定義的欄位外,還有資料庫隱式定義的DB_TRX_ID,DB_ROLL_PTR,DB_ROW_ID等欄位
id: 1 name zhangsan 事務id:1
-
DB_TRX_ID
6byte,最近修改(修改/插入)事務ID:記錄創建這條記錄/最后一次修改該記錄的事務ID -
DB_ROLL_PTR
7byte,回滾指標,指向這條記錄的上一個版本(存盤于rollback segment里)undo日志記錄了很多操作當前的這條資料,得找到對應得日志,靠指標
-
DB_ROW_ID
6byte,隱含的自增ID(隱藏主鍵),如果資料表沒有主鍵,InnoDB會自動以DB_ROW_ID產生一個聚簇索引 -
實際還有一個洗掉flag隱藏欄位, 既記錄被更新或洗掉并不代表真的洗掉,而是洗掉flag變了

undo日志只是記錄得事務操作得反向操作.
A事務正在執行,把buffer age改成25,但是沒有提交
B事務來讀取資料,應該讀取24,24哪兒來呢
Read View
什么是Read View,說白了Read View就是事務進行快照讀操作的時候生產的讀視圖

當每個事務開啟時,都會被分配一個ID, 這個ID是遞增的,所以最新的事務,ID值越大
Read View簡單的理解成有三個全域屬性:
trx_list
一個數值串列,用來維護Read View生成時刻系統正活躍的事務ID
例如:
我自己的事務時事務2
1操作未提交 3操作未提交 4已經提交 放入trx_list:[1,3]
low_limit_id
記錄trx_list串列中事務ID最小的ID 就是1
next_limit_id
ReadView生成時刻系統尚未分配的下一個事務ID,也就是目前已出現過的事務ID的最大值+1
5
1.如果當前buffer里面的事務id x小于trx_list里面的最小id(low_limit_id) 可以讀取這個事務id x的資料
事務2開啟,事務3開啟,我是事務4,事務5 , 事務id是自增的 buffer的順序應該1-2-3-4-5,那個事務最近操作了我,事務id就是誰
事務4開啟事務,生成快照讀,讀取到buffer中當前欄位的隱藏事務id是1. 因為事務1的操作一定在2345前面,所以事務id能為1一定是事務1回滾或者提交了
第一條滿足就不會走后面
2.如果第一條沒有滿足,比較讀取到buffer中的事務id,比next_limit_id還大,不可讀取,我生成快照的時候最大值就是5,你比5還大說明生成快照的時候壓根沒有開啟這個事務,肯定不能讀取,
3.2條滿足的情況下,把在buffer中讀取到的事務id,去trx_list里面遍歷,如果trx_list里面有說明還在活躍,不能讀取,否則可以讀取
因為這三條,使用mvcc 樂觀鎖來保證并發隔離性,并沒有加鎖

讀已提交RC read-commited
會出現不可重復讀
A事務: 第一次select 生成快照
? 第二次select 又會生成快照
? 每一次都會生成快照
會不會臟讀?不會,因為上面的mvcc條件判斷
會不會不可重復讀呢?會出現, 比如上面的例子,第一次4提交,3沒有提交,buffer中的事務id是4 根據條件4滿足直接讀取,如果第二次快照3提交了,buffer中事務id是3,根據地址,直接定位3的版本鏈.兩次的結果不一致
readview會改變
解決不可重復讀RR read-repeatable
只是多次讀取,只會有一次快照
A事務: 第一次select 生成快照
? 第二次select 不會生成
肯定避免了不可重復讀
A事務第一次讀取了,另外一個事務修改了,A事務再次讀取資料一致
解決不了幻讀
如果只是多次讀取是可以解決幻讀的,因為不會出現當前讀,只會生成一次快照,
1.a事務先select(觸發快照生成),b事務insert確實會加一個gap鎖,但是如果b事務commit,這個gap鎖就會釋放(釋放后a事務可以隨意操作), student表9條資料,生成快照,b事務插入/洗掉了一條資料,并且提交
2.a事務再select出來的結果在MVCC下還和第一次select一樣,不會幻讀,生成了一次快照了不會再次生成,沒有幻讀
3.接著a事務不加條件地update,這個update會作用在所有行上(包括b事務新加的),
? update 需要更新全表
?
? 增刪改觸發鎖,觸發當前讀,需要讀取最新的資料,讀取到10條
4.a事務再次select就會出現b事務中的新行,并且這個新行已經被update修改了. 剛才的快照讀已經丟失了,因為在中間有一次當前讀
上面這樣,事務2提交之后,事務1再次執行update,因為這個是當前讀,他會讀取最新的資料,包括別的事務已經提交的,所以就會導致此時前后讀取的資料不一致,出現幻讀,

InnoDB有三種行鎖的演算法:
盡量彌補錯誤,
1,Record Lock:單個行記錄上的鎖,
2,Gap Lock:間隙鎖,鎖定一個范圍,但不包括記錄本身,GAP鎖的目的,是為了防止同一事務的兩次當前讀,出現幻讀的情況,
3,Next-Key Lock:1+2,鎖定一個范圍,并且鎖定記錄本身,對于行的查詢,都是采用該方法,主要目的是解決幻讀的問題

超時時間的引數:innodb_lock_wait_timeout ,默認是50秒,
超時是否回滾引數:innodb_rollback_on_timeout 默認是OFF,
默認情況下,InnoDB存盤引擎不會回滾超時引發的例外,除死鎖外,
因為InnoDB對于行的查詢都是采用了Next-Key Lock的演算法,鎖定的不是單個值,而是一個范圍,按照這個方法是會和第一次測驗結果一樣,但是,當查詢的索引含有唯一屬性的時候,Next-Key Lock 會進行優化,將其降級為Record Lock,即僅鎖住索引本身,不是范圍,
注意:通過主鍵或則唯一索引來鎖定不存在的值,也會產生GAP鎖定
如何讓測驗一不阻塞?可以顯式的關閉Gap Lock:
1:把事務隔離級別改成:Read Committed,提交讀、不可重復讀,SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
2:修改引數:innodb_locks_unsafe_for_binlog 設定為1,
mvcc+間隙鎖:完成了事務隔離性,但是依然沒有徹底解決幻讀吧
5.總結
對ACID的回答要提高,幻讀,不可重復讀
undo日志:保證原子性
redo日志:保證持久性
mvcc+鎖:保證隔離性
原子性+持久性+隔離性=一致性(最終目的)
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/242951.html
標籤:其他
