天天看點

MySQL事務與并發

MySQL事務與并發

很多程式員都學過MySQL,而且也會寫SQL語句。但僅僅會寫還遠遠不夠,在面試中以及在工作中,還必須要會事務和并發。

一、事務

事務是滿足 ACID 特性的操作,可以通過 Commit 送出事務,也可以使用 Rollback 進行復原。

A(Atomicity)原子性:事務被視為不可分割的小單元,事務的所有操作要麼全部送出成功,要麼全部失敗復原。

C(Consistency)一緻性:資料庫在事務執行前後都保持一緻性狀态。在一緻性狀态下,所有事務對一個資料的讀取結果都是相同的。

I(Isolation)隔離性:事務之間的操作是互相隔離的。

D(Durability)持久性:一旦事務送出,則其所做的修改将會永遠儲存到資料庫中。

二、并發一緻性

在并發環境下,容易造成并發一緻性問題,導緻隔離性被破壞。假設目前有兩個事務,分别命名為A和B,在并發環境下,容易出現以下問題。

丢失更新:A、B同時修改資料,A先,B後,A送出後B送出,B操作覆寫了A的操作,導緻A丢失更新。

讀髒資料:A修改資料,B讀取資料;随後A撤銷操作,則B讀到髒資料。

不可重複讀:B讀取資料,A修改資料,B再次讀取資料,發現資料和第一次讀時不一緻。

幻讀:A讀取了某個範圍的資料,B在此範圍内插入一條資料;A再次讀取,結果不一樣。

三、鎖

在并發環境下,為解決并發一緻性問題保證事務的隔離性,可采取封鎖機制。當一個事務在進行操作時加鎖,限制另一個事務的操作。

一般而言,為保證效率,鎖的粒度不宜太大。在MySQL中,提供了行鎖和表鎖。

行鎖:事務A操作資料時,隻封鎖被操作的行,事務B可以操作其他行的資料,并發程度高;

表鎖:事務A操作資料時,封鎖整個表,事務B要等A完成才能操作,并發度較低。

在讀寫方面資料庫鎖也分為讀鎖(共享鎖)和寫鎖(排他鎖)。

讀鎖:若事務A加了此鎖,A可以對資料進行讀取操作,但不能更新;其它事務也可以讀,但不能修改;

寫鎖:若事務A加了此鎖,A可以對資料進行讀和寫操作,其它事務不能讀寫,否則會阻塞。

上面所說的是悲觀鎖,MySQL中InnoDB也提供了樂觀鎖的實作——MVCC(多版本并發控制)。用通俗的方式解釋悲觀鎖和樂觀鎖大概是這樣:​

悲觀鎖:認為每次操作都會修改資料,每次都在操作前上鎖;​

樂觀鎖:認為每次操作都不會修改資料,不上鎖,但是會記錄一個版本号或者時間戳,用來對比。

​MVCC則是樂觀鎖的實作,它在每行記錄後面都儲存着兩個隐藏的列,用來存儲建立版本号和删除版本号。

四、隔離級别

若鎖的操作要使用者自己控制,會比較複雜,是以資料庫管理系統提供了事務的隔離級别,使問題簡單化。MySQL的隔離級别有四種,分别是:未送出讀、已送出讀、可重複讀、可序列化。它們與并發一緻性問題的關系如下表所示。MySQL預設隔離級别為:可重複讀

未送出讀:事務修改資料,即使未送出,其它事務依舊可見。

已送出讀:事務修改資料送出之前,其他事務不可見。

可重複讀:事務多次讀取資料的結果都一樣。

可序列化:解決了幻讀問題。

五、存儲引擎

說到資料庫的并發問題,就要提一下MySQL的存儲引擎。MySQL的存儲引擎有很多種,最常用的還是MyISAM和InnoDB,它們的差別如下:

是以,一般在讀操作比較多的情況下,MyISAM的效率更高,因為相比于InnoDB,它維護的東西要少,比如版本号,索引資料等。

但是InnoDB支援事務,而且在并發環境下優勢顯著。至于如何選擇存儲引擎,應根據具體情況而定。

總結

本文講了資料庫的事務以及并發一緻性問題,并且引申出解決辦法以及MySQL的存儲引擎。這些知識,對于絕大多數從事網際網路工作的人來說,是必須要掌握的,也是在面試中經常考察的點。

原文位址

https://www.cnblogs.com/lyuzt/p/12810150.html