Mysql關於事務的幾個常見概念

目錄

 

一、事務

二、事務4大屬性(ACID)

三、事務4種隔離級別

四、mysql事務查看與隔離級別設置

補充:InnoDB支持顯示鎖定:


 

一、事務

首先,我們要理解什麼是事務?

在計算機中,事務是指訪問並可能更新數據庫中數據的一個獨立工作單元。這個工作單元可能由一條或者多條sql語句組成,事務內的語句要麼全部執行成功,要麼全部執行失敗,以此保證數據庫中數據的完整一致性。

舉個生活中比較容易理解的例子:例子中的每一條信息假設是一條sql。

1.我先去銀行取款機查看卡里有多少錢

2.將身上的500元錢存進去

3.突然想起來沒錢喫飯了,又取出來200元

你一定不會希望500塊錢存到自助存款機了,但是賬上卻沒多出500;銀行也不會願意取款機吐出了200元錢,賬上卻沒扣掉200元,道理就是這麼簡單。

所以,如何保證最終結果正確,上面的三個步驟可以理解成一個工作單元:3個步驟必須打包成一個整體,才能保證銀行卡里餘額最終的正確性,要麼都成功,要麼都失敗。

 

二、事務4大屬性(ACID)

A:原子性    C:一致性     I:隔離性      D:持久性

1.原子性atomicity:一個事務必須被視爲一個不可再分割的最小工作單元,不管是有多少個sql語句組成,要麼全部成功,要麼全部失敗,這就是事務的原子性。

2.一致性consistency:數據庫總是從一種一致性的狀態轉換到另外一個一致性的狀態,意思就是sql所做的一系列修改,如果事務沒有提交,事務中所做的修改也不會保存到數據庫中。

3.隔離性isolation:一個事務所作的修改在最終提交以前,對其它的事務是不可見的。也就是說事務之間是不該互相產生干擾的。

4.持久性durabil:一旦事務提交,則其所做的修改就會永久保存到數據庫中。哪怕數據庫宕機了,當數據庫服務重啓以後,數據依然是存在的。

 

三、事務4種隔離級別

1.READ UNCOMMITTED:

未提交讀:事務中的修改,即時沒有提交,對其它的事務也都是可見的。那麼,這樣就容易導致一個常見的問題,就是一個事務A可能讀取到另一個未提交的事務B所修改的數據,這種現象也被稱爲髒讀。因此,實際開發中,很少使用到這種隔離級別。

2.READ COMMITTED:

提交讀:大多數數據庫系統的默認隔離級別都是READ COMMITTED(MySQL不是)。該級別滿足了事務隔離性的特點,即一個事務從開始到提交之前,所做的任何修改對其它事務都是不可見的。但是這個級別有時候也叫不可重複讀,因爲兩次執行同樣的查詢,可能會得到不一樣的結果。可能在業務中第一次查詢某個記錄是A,然後進行其它的業務處理,業務完後你想回去再看看那條記錄是否是A,結果再查詢就卻變成了B的這種現象。

3.REPEATABLE READ:(mysql默認的隔離級別)

可重複讀:該級別解決了髒讀的問題,也保證在同一個事務中多次讀取同樣記錄的結果是一致的。但是無法解決另外一個幻讀的問題。即當某個事務在讀取某個範圍內的記錄時,另外一個事務又在該範圍內插入了新的記錄,當之前事務再次讀取該範圍數據的時候,會產生幻行。InnoDB和XtraDB存儲引擎通過多版本併發控制(MVCC)解決了幻讀的問題。

4.SERIALIZABLE:

可串行化:該級別是最高隔離級別。它的原理其實就是通過強制事務串行執行,避免了前面所說的幻讀的問題。由於強制串行化執行是通過在讀取的每一行數據上加鎖實現的,所以很容易導致大量的超時等待和鎖衝突的問題,實際應用中也很少使用該隔離級別。除非非常需要確保數據的一致性且沒有併發的情況,才能使用該級別。

 

隔離級別 髒讀可能性 不可重複的可能性 幻讀可能性 加鎖讀
READ UNCOMMITTED YES YES YES NO
READ COMMITTED NO YES YES NO
REPEATABLE READ NO NO YES NO
SERIALIZABLE NO NO NO YES

 

四、mysql事務查看與隔離級別設置

1.查看是否開啓事務自動提交,如果value的值是ON,則表示默認提交事務;MyISAM存儲引擎或者內存表等非事務型的表不會受是否開啓默認提交事務影響,其始終處於自動提交狀態。InnoDB存儲引擎會受到其影響。

show VARIABLES like "autocommit"

2.設置隔離級別:

先查看隔離級別:

select @@tx_isolation;

或者如下,因爲版本不一樣,可能有點區別

show variables like 'transaction_isolation'

再設置隔離級別:

-- 可以選擇如下四種隔離級別
-- READ UNCOMMITTED
-- READ COMMITTED
-- REPEATABLE READ
-- SERIALIZABLE

set session TRANSACTION ISOLATION LEVEL READ COMMITTED

 

 

補充:InnoDB支持顯式鎖定:

通過select ... FOR UPDATE 來給查詢顯式加鎖,屬於悲觀鎖,有些業務考慮到接口冪等性,sql可以這樣操作上鎖,不適合併發高的業務,容易造成鎖等待或鎖超時。

1.首先我們有一個簡單的用戶表:

2.執行開啓事務並查詢,但不提交事務的操作;

BEGIN;

SELECT * from  `user` where id = 1 for update;

-- 先不提交事務
COMMIT;

3.執行更新語句,修改id=1的name信息;

UPDATE `user` set name = "tomupdate" where id = 1 

我們可以發現更新一直在等待中,原因就是我們在第一步查詢的末尾添加了 FOR UPDATE語句且未提交事務;更新語句等待很久遲遲獲取不到鎖,就會報鎖等待超時,提示如下截圖;

 

4.鎖超時以後,我們再執行一次更新,在鎖超時以前,將查詢用戶的commit語句執行一下,完成事務的提交。提交以後,我們就可以發現更新語句立即更新成功,原因就是查詢語句完成事務且釋放了顯式添加的鎖。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章