事務(wù)定義
一組原子性SQL查詢委可,獨(dú)立的工作單元
ACID(atomicity-原子性,consistency-一致性,isolation-隔離性,durability-持久性)
- 事務(wù)不可分割
- 從一個(gè)一致性狀態(tài)轉(zhuǎn)到另一個(gè)一致性狀態(tài)
- 事務(wù)修改提交之前對(duì)其他事務(wù)不可見
- 一旦提交,永遠(yuǎn)保存
根據(jù)業(yè)務(wù)是否需要事務(wù)腊嗡,選擇合適的儲(chǔ)存引擎着倾,提升性能
若存儲(chǔ)引擎不支持事務(wù)也可以使用locktable提供一定保護(hù)
隔離級(jí)別
- 臟讀(dirty read):事務(wù)讀取了未提交的數(shù)據(jù)
- 不可重復(fù)讀(nonrepeatable read):事務(wù)T1讀取一行記錄拾酝,緊接著事務(wù)T2修改了T1剛才讀取的那一行記錄,然后T1又再次讀取這行記錄屈呕,發(fā)現(xiàn)與剛才讀取的結(jié)果不同
- 幻像讀(phantom read):當(dāng)某個(gè)事務(wù)在讀某個(gè)范圍內(nèi)的記錄時(shí),另一個(gè)事務(wù)又在該范圍內(nèi)加入了新的記錄棺亭,當(dāng)之前的事務(wù)再讀取該范圍的記錄時(shí)虎眨,會(huì)產(chǎn)生幻行。InnoDB和XtraDB存儲(chǔ)引擎通過MVCC解決了幻像讀的問題
READ UNCOMMITTED(未提交讀)
: 事務(wù)的修改即使未提交镶摘,對(duì)其他事務(wù)也可見嗽桩,性能略好,但有很多問題凄敢,不建議使用
READ COMMITTED(提交讀)
: 事務(wù)所做的修改在提交前對(duì)其他事務(wù)不可見碌冶,大多數(shù)數(shù)據(jù)庫默認(rèn)隔離級(jí)別
REPEATABLE READ(可重復(fù)讀)
: 同一事務(wù)多次讀取的記錄結(jié)果是一致的,Mysql默認(rèn)級(jí)別
SERIALIZABLE(序列化)
: 強(qiáng)制事務(wù)串行執(zhí)行,會(huì)對(duì)讀取的每一行數(shù)據(jù)加鎖涝缝,會(huì)導(dǎo)致大量的超時(shí)和鎖爭用扑庞,用在非常需要確保數(shù)據(jù)的一致性并且可以接受沒有并發(fā)的情況下
事務(wù)的隔離級(jí)別|臟讀可能性|不可重復(fù)讀可能性|幻像讀可能性|備注
--|--|--|---
READ UNCOMMITTED未提交讀|YES|YES|YES
READ COMMITTED提交讀|No|YES|YES
REPEATABLE READ可重復(fù)讀|No|No|YES|Mysql默認(rèn)級(jí)別
SERIALIZABLE序列化|No|No|No|會(huì)在讀取的每一行數(shù)據(jù)上都加鎖
死鎖
多個(gè)事務(wù)在同一資源上互相占用,并請(qǐng)求鎖定對(duì)方占用的資源拒逮,從而導(dǎo)致惡性循環(huán)
- 多個(gè)事務(wù)以不同的順序鎖定資源
- 多個(gè)事務(wù)同時(shí)鎖定同一資源
解決方式:1. 檢測(cè)到死鎖時(shí)罐氨,立刻返回錯(cuò)誤 2. 當(dāng)查詢的時(shí)間達(dá)到鎖等待超時(shí)的設(shè)定后放棄鎖請(qǐng)求
InnoDB處理方式
: 將持有最少行級(jí)排他鎖的事務(wù)進(jìn)行回滾
發(fā)生死鎖后,只有部分或者完全回滾其中一個(gè)事務(wù)滩援,才能打破死鎖栅隐。發(fā)生死鎖無法避免,程序設(shè)計(jì)時(shí)需要考慮如何處理死鎖玩徊,通常重新執(zhí)行因死鎖回滾的事務(wù)即可
事務(wù)日志
提高事務(wù)的效率
:
- 存儲(chǔ)引擎在修改表的數(shù)據(jù)時(shí)只需要修改其內(nèi)存拷貝租悄,再把該修改行為記錄到持久在硬盤上的事務(wù)日志中,而不用將修改的數(shù)據(jù)本身持久到磁盤恩袱。
- 事務(wù)日志采用的是追加的方式泣棋,寫日志的操作是在磁盤上的一小塊順序I/O,不像隨機(jī)I/O需要在多次移動(dòng)磁頭畔塔。
事務(wù)日志持久后外傅,內(nèi)存被修改的數(shù)據(jù)在后臺(tái)慢慢刷回到磁盤。稱為預(yù)寫式日志(Write-Ahead Logging)俩檬,修改數(shù)據(jù)需要寫兩次磁盤.
若數(shù)據(jù)的修改已經(jīng)記錄到日志并持久化萎胰,即使內(nèi)存的修改沒及時(shí)寫到磁盤,也可以在存儲(chǔ)引擎重啟時(shí)自動(dòng)恢復(fù)
MySQL事務(wù)
官方提供的事務(wù)存儲(chǔ)引擎:InnoDB和NDB Cluster
第三方:XtraDB和PBXT
自動(dòng)提交
mysql默認(rèn)會(huì)啟用自動(dòng)提交棚辽,每個(gè)查詢都會(huì)被當(dāng)作一個(gè)事務(wù)執(zhí)行提交操作技竟,在當(dāng)前連接中可以設(shè)置AUTOCOMMIT 1/ON或0/OFF。
導(dǎo)致大量數(shù)據(jù)改變的操作ALTER TABLE,還有LOCK TABLES等也會(huì)導(dǎo)致自動(dòng)提交
事務(wù)中混合使用存儲(chǔ)引擎
- 在非事務(wù)型的表上屈藐,回滾操作無效榔组,且不會(huì)報(bào)錯(cuò)熙尉,只會(huì)有警告信息
為每張表選擇合適的存儲(chǔ)引擎
隱式、顯式鎖定
- InnoDB使用兩段鎖定協(xié)議搓扯,事務(wù)執(zhí)行時(shí)检痰,可隨時(shí)執(zhí)行鎖定,只要到COMMIT或ROLLBACK時(shí)才會(huì)同時(shí)釋放所有鎖锨推,InnoDB會(huì)根據(jù)隔離級(jí)別自動(dòng)加鎖(隱式)
- SELECT ... LOCK IN SHARE MODE和 SELECT ... FOR UPDATE 顯式鎖定铅歼,但不建議使用
LOCK TABLES、UNLOCK TABLES
服務(wù)器層實(shí)現(xiàn)换可,不能代替事務(wù)椎椰,且影響性能
MVCC多版本并發(fā)控制
- 行級(jí)鎖變種 能盡量避免加鎖 開銷低
此處介紹InnoDB對(duì)MVVC的實(shí)現(xiàn)
實(shí)現(xiàn)原理
: 在每行記錄后保存兩個(gè)隱藏的列,一個(gè)保存行創(chuàng)建時(shí)間沾鳄,一個(gè)保存過期(刪除)時(shí)間慨飘,此處的時(shí)間指的是系統(tǒng)版本號(hào),它會(huì)在創(chuàng)建事務(wù)時(shí)遞增译荞,
具體操作
:
- SElECT
- 只查找版本號(hào)小號(hào)或等于當(dāng)前事務(wù)的版本號(hào)瓤的,確保讀取的行,或是在事務(wù)開始之前吞歼,或是事務(wù)自己插入的
- 行的刪除版本要么未定義堤瘤,要么大于當(dāng)前事務(wù)版本號(hào),確保事務(wù)讀到行在事務(wù)開始之前未被刪除
- INSERT
- 插入的每一行保存當(dāng)前系統(tǒng)版本號(hào)作為行版本號(hào)
- DELETE
- 插入的每一行保存當(dāng)前系統(tǒng)版本號(hào)作為行版本號(hào)
- UPDATE
- 為插入的新記錄保存當(dāng)前系統(tǒng)版本號(hào)作為行版本號(hào)浆熔,同時(shí)保存當(dāng)前系統(tǒng)版本號(hào)到原來的行作為行刪除標(biāo)識(shí)