一、MySQL 是如何實現(xiàn)四大隔離級別的
首先說讀未提交,它是性能較好,也可以說它是最野蠻的方式,因為它壓根兒就不加鎖,所以根本談不上什么隔離效果,可以理解為沒有隔離。
再來說串行化。讀的時候加共享鎖,也就是其他事務可以并發(fā)讀,但是不能寫。寫的時候加排它鎖,其他事務不能并發(fā)寫也不能并發(fā)讀。
最后說讀提交和可重復讀。這兩種隔離級別是比較復雜的,既要允許一定的并發(fā),又想要兼顧的解決問題。
為了解決不可重復讀,或者為了實現(xiàn)可重復讀,MySQL 采用了 MVVC (多版本并發(fā)控制) 的方式。
我們在數(shù)據(jù)庫表中看到的一行記錄可能實際上有多個版本,每個版本的記錄除了有數(shù)據(jù)本身外,還要有一個表示版本的字段,記為 row trx_id,而這個字段就是使其產(chǎn)生的事務的 id,事務 ID 記為 transaction id,它在事務開始的時候向事務系統(tǒng)申請,按時間先后順序遞增。
一行記錄現(xiàn)在有 3 個版本,每一個版本都記錄這使其產(chǎn)生的事務 ID,比如事務A的transaction id 是100,那么版本1的row trx_id 就是 100,同理版本2和版本3。
在上面介紹讀提交和可重復讀的時候都提到了一個詞,叫做快照,學名叫做一致性視圖,這也是可重復讀和不可重復讀的關鍵,可重復讀是在事務開始的時候生成一個當前事務全局性的快照,而讀提交則是每次執(zhí)行語句的時候都重新生成一次快照。
對于一個快照來說,它能夠讀到那些版本數(shù)據(jù),要遵循以下規(guī)則:
當前事務內(nèi)的更新,可以讀到;
版本未提交,不能讀到;
版本已提交,但是卻在快照創(chuàng)建后提交的,不能讀到;
版本已提交,且是在快照創(chuàng)建前提交的,可以讀到;
利用上面的規(guī)則,再返回去套用到讀提交和可重復讀的那兩張圖上就很清晰了。還是要強調(diào),兩者主要的區(qū)別就是在快照的創(chuàng)建上,可重復讀僅在事務開始是創(chuàng)建一次,而讀提交每次執(zhí)行語句的時候都要重新創(chuàng)建一次。
存在這的情況,兩個事務,對同一條數(shù)據(jù)做修改。最后結(jié)果應該是哪個事務的結(jié)果呢,肯定要是時間靠后的那個對不對。并且更新之前要先讀數(shù)據(jù),這里所說的讀和上面說到的讀不一樣,更新之前的讀叫做“當前讀”,總是當前版本的數(shù)據(jù),也就是多版本中最新一次提交的那版。
假設事務A執(zhí)行 update 操作, update 的時候要對所修改的行加行鎖,這個行鎖會在提交之后才釋放。而在事務A提交之前,事務B也想 update 這行數(shù)據(jù),于是申請行鎖,但是由于已經(jīng)被事務A占有,事務B是申請不到的,此時,事務B就會一直處于等待狀態(tài),直到事務A提交,事務B才能繼續(xù)執(zhí)行,如果事務A的時間太長,那么事務B很有可能出現(xiàn)超時異常。加鎖的過程要分有索引和無索引兩種情況,比如下面這條語句
update user set age=11 where id = 1
id 是這張表的主鍵,是有索引的情況,那么 MySQL 直接就在索引數(shù)中找到了這行數(shù)據(jù),然后干凈利落的加上行鎖就可以了。
而下面這條語句
update user set age=11 where age=10
表中并沒有為 age 字段設置索引,所以, MySQL 無法直接定位到這行數(shù)據(jù)。那怎么辦呢,當然也不是加表鎖了。MySQL 會為這張表中所有行加行鎖,沒錯,是所有行。但是呢,在加上行鎖后,MySQL 會進行一遍過濾,發(fā)現(xiàn)不滿足的行就釋放鎖,最終只留下符合條件的行。雖然最終只為符合條件的行加了鎖,但是這一鎖一釋放的過程對性能也是影響極大的。所以,如果是大表的話,建議合理設計索引,如果真的出現(xiàn)這種情況,那很難保證并發(fā)度。
延伸閱讀:
二、什么是數(shù)據(jù)庫和數(shù)據(jù)庫管理系統(tǒng)
數(shù)據(jù)庫的應用非常廣泛,舉個例子,我們平時在瀏覽器上搜索內(nèi)容,就要用到數(shù)據(jù)庫去檢索我們的關鍵字。以前我們可能會用數(shù)組、集合、文件等來存儲數(shù)據(jù),但是接下來我們就會面臨一個問題,當存儲的數(shù)據(jù)或內(nèi)容過多的時候,我們?nèi)绾稳ゾ珳实恼业轿覀冃枰臇|西,這時候數(shù)據(jù)庫管理系統(tǒng)就派上了用場。除此之外,數(shù)據(jù)庫管理系統(tǒng)還能永久的儲存我們的數(shù)據(jù)。
為了便于大家理解,這里先給大家講解幾個概念
DB數(shù)據(jù)庫(database):存儲數(shù)據(jù)的“倉庫”。它保存了一系列有組織的數(shù)據(jù)。
DBMS數(shù)據(jù)庫管理系統(tǒng)(Database Management System):數(shù)據(jù)庫是通過DBMS創(chuàng)建和操作的容器。
SQL,結(jié)構(gòu)化查詢語言(Structured Query Language)用一句話概括,SQL是一種特殊目的的編程語言,一種專門用來與數(shù)據(jù)庫通信的語言。在數(shù)據(jù)庫中,數(shù)據(jù)被結(jié)構(gòu)化并存儲在不同的表中,從而簡化了訪問,更新和操作數(shù)據(jù)的過程。該表由列和行組成。數(shù)據(jù)庫中的表可以在關系的幫助下進行連接。要在數(shù)據(jù)庫中執(zhí)行與數(shù)據(jù)相關的任務,可以使用SQL。SQL代表結(jié)構(gòu)化查詢語言,旨在在特定RDBMS內(nèi)創(chuàng)建,修改和管理數(shù)據(jù)庫中的數(shù)據(jù)。
SQL優(yōu)點:
1、不是某個特定數(shù)據(jù)庫供應商專有的語言,幾乎所有DBMS(數(shù)據(jù)庫管理系統(tǒng))都支持SQL
2、簡單易學
3、雖然簡單,但實際上是一種強有力的語言,靈活使用其語言元素,可以進行非常復雜和高級的數(shù)據(jù)庫操作。