目錄
原子性
持久性?
隔離性
隔離級別(并發事務之間的關系)
讀未提交
讀已提交
可重復讀
串行化(最嚴格的隔離級別)
一致性
問題
不可重復讀性(已經提交的數據)
什么是臟讀問題(未提交的數據)?
幻讀
保存點
自動提交機制--autocommit
會話隔離級別與全局隔離級別
原子性
事務原子性是指在數據庫操作中,事務要么全部執行成功,要么全部執行失敗,不存在部分執行成功部分執行失敗的情冿。事務原子性保證了數據的一致性和可靠性,確保數據庫中的數據不會出現不一致的情況。當一個事務中的所有操作都成功完成時,事務被提交;當有任何一個操作失敗時,事務將會被回滾,使得數據回到事務開始之前的狀態。這樣保證了數據庫中的數據始終處于一致的狀態。
持久性?
事務持久性是指一旦事務成功提交,其所做的改變就會永久保存在數據庫中,即使系統發生故障或意外斷電也不會丟失。數據庫系統通過將事務的操作記錄持久化保存在磁盤上來實現事務的持久性,確保數據庫的一致性和可靠性。要實現事務的持久性,數據庫系統通常會使用日志記錄和事務提交機制來保證事務的持久性。
隔離性
隔離級別(并發事務之間的關系)
隔離怎么理解?
隔離級別是相對于自己的事務還是其他事務
-->是相對于自己會話的事務來說的,先簡單的拿讀已提交為例;
自己會話的事務讀取其他客戶端的事務的數據必須是已經提交的;并不是自己設置事務為讀已提交,其他客戶端的事務就讀不到的我的事務的數據了,有可能其他事務設置的是讀未提交,如此,可以實時的獲取我的事務的數據;
讀未提交
那么什么是讀未提交級別呢?
-->可以讀到未提交的數據。就這么簡單。
默認情況下,我開啟了一個事務,還向表中插入了一行元組,但是我沒有提交事務,由于事務的隔離性,其他事務是讀不到我新插入的一行數據的,只能讀到這個事務之前的數據;
但是,現在我把事務隔離級別設置為是“讀未提交”,那么即便我不提交事務,其他客戶端也可以讀到我這個新插入的數據了;
總結:讀未提交隔離級別下,事務的任何修改都是透明的,,都可以被其他客戶端讀到,但是他們沒法訪問;
代碼示例:
設置全局事務隔離級別(讀未提交):
Set global transaction isolation level read uncommitted;
查看全局事務級別:
SELECT @@transaction_isolation;
?向表中插入一行數據但不commit,我們會發現右邊的事務也能夠看到新數據;
解釋:
開啟事務,向price表中插入一行數據,但不提交,再打開一個客戶端,查看price表,發現新增了一條數據,
insert into price values(1,"小小",500);
事務回滾,重新查看price表,發現剛才的元組沒了;
讀已提交
只能讀到其他事務已經提交的數據;如果別的客戶端不提交事務,那么我們就讀到的始終是舊數據;
設置隔離級別SQL語句: set? session transaction isolation level read committed;
可重復讀
可重復讀,我們可以這么理解,我們設置當前會話隔離級別是可重復讀,那么意思就是"放心讀,不用擔心數據會更改",事實是,他跟讀已提交的區別就在于即便有其他事務把數據更改了提交了,我當前事務讀到的數據依舊是原來的數據,不會改變,這就是可重復讀;
所以可重復讀級別下讀到的數據是其他事務開始之前的數據;即便其他事務提交了,讀到的數據也不會發生變化;
串行化(最嚴格的隔離級別)
將所有的事務串行執行,同一時間只有一個事務在執行;類似與加鎖;--->效率問題
一致性
一致性簡單來講就是對數據的操作要合理;
比如:小紅轉給小明100塊錢,那最后的結果就是小紅余額減少100元,小明的余額增加100元,這就是要保持一致,如果小紅的余額沒減貨或者小明的余額沒增,那就是不一致;
?一致性算是一種目的和要求,通過前面的原子性,隔離性,持久性來保證事務的一致性;
問題
不可重復讀性(已經提交的數據)
在MySQL事務中,不可重復讀(non-repeatable read)是指在同一個事務中多次讀取相同的數據,但在讀取過程中數據發生了變化,導致多次讀取的結果不一致的情況。這可能會導致事務在處理過程中出現異常或錯誤的情況。
不可重復讀的典型例子如下:
- 事務A在讀取一行數據后,事務B修改了這行數據,然后事務A再次讀取同一行數據,此時讀取的數據已經發生了變化,造成不一致。
- 事務A在讀取一批數據后,事務B刪除了其中的一部分數據,然后事務A再次讀取同一批數據,發現有部分數據已經被刪除,導致不一致。
簡單來說就是,我沒有把握確定當前數據具體的值,因為他隨時可能變化;?
什么是臟讀問題(未提交的數據)?
其他事務讀到的數據可能被修改了,比如,事務A開啟事務,事務B讀到了一個數據行。但是B事務讀取完畢后,事務A馬上就修改了那一個數據行,所以就造成了事務B拿到的數據是"假數據",這就是"臟讀“;
幻讀
幻讀是指一個事務在執行過程中,按照相同的查詢條件多次查詢,由于其他事務插入或刪除了滿足查詢條件的新數據,導致結果集的行數發生變化。
重點:其他事務插入貨刪除數據,導致的結果集發生變化;
哪種隔離級別會出現幻讀現象?
-->讀未提交,讀已提交;
這兩種都是我在執行事務的時候可以讀到別的事務操作過的數據;
保存點
SQL語句:savepoint 保存點名稱;
開啟事務后,可以通過設置保存點決定回滾到哪一次保存前的內容
示例:
準備好的一個表;
?我向表中插入了兩行數據,插入后保存了兩個保存點;
?現在我們回到保存點s1處的狀態;我們會發現表就是s1保存時的狀態;
?現在試試能不能回到s2了;-->是無法回到時間點后面的保存點的;
自動提交機制--autocommit
SQL語句:Set autocommit=1(默認就是自動提交的)
?因為默認就是自動提交的所以我這里設為不自動提交;
?什么是默認提交呢?
-->顧名思義,就是我執行完任意一條SLQ語句后都相當于是一個事務,自動commit;
我們平時寫的一個SQL語句就是一個事務;
下面我們來驗證下,在不自動提交的情況下是什么樣的:
首先,左邊的我設置為不自動提交,右邊的設置為自動提交,隔離級別都是可重復讀;
?我插入在左邊的客戶端向表中插入了一行數據,但是不commit;我們發現右邊查不到新的數據,這是因為左邊的事務沒有提交,一個SQL語句已經不再是一個完整的事務了。
下面把左邊的事務提交了試試看,發現左邊的事務提交了之后,右邊才可以看到新的數據行;
會話隔離級別與全局隔離級別
會話隔離級別:設置當前客戶端的隔離級別,不會影響到其他的客戶端的隔離級別。
全局隔離級別:設置所有客戶端的隔離級別,對象是該服務端對應的所有的客戶端;
簡單來講,一個是全局變量,一個是局部變量;使用的時候是局部優先,因此我們修改會話級別的時候記得修改當前會話的級別,如果修改的是全局的隔離級別,其實還是使用的局部的會話隔離級別,記得檢查一下;