1.資料庫事務概述
事務是資料庫區別於檔案系統的重要特性之一,當我們有了事務就會讓資料庫始終保持一致性
,同時我們還能透過事務的機制恢復到某個時間點
,這樣可以保證已提交到資料庫的修改不會因為系統崩潰而丟失。
1.1 儲存引擎支援情況
SHOW ENGINES
命令來檢視當前MySQL支援的儲存引擎都有那些,以及這些儲存引擎是否支援事務。
從執行結果來看,在MySQL中,只有InnoDB是支援事務。
1.2 基本概念
事務:一組邏輯操作單元,使資料從一種狀態變換到另一種狀態。
事務處理的原則:保證所有事務都作為一個工作單元
來執行,即使出現了故障,都不能改變這種執行方式。當在一個事務中執行多個操作時,要麼所有的事務都被提交(commit
),那麼這些修改就永久
地儲存下來要麼資料庫管理系統將放棄
所作的所有修改
,整個事務回滾( rollback
)到最初狀態。
-- 案例:AA使用者給BB使用者轉賬100
update account set money = money - 100 where name = 'AA’;
-- 伺服器當機
update account set money = money + 100 where name = 'BB';
1.3 事務的ACID特性
- 原子性( atomicity ):
原子性是指事務是一個不可分割的工作單位,要麼全部提交,要麼全部失敗回滾。即要麼轉賬成功,要麼轉賬失敗,是不存在中間的狀態。如果無法保證原子性會怎麼樣?就會出現資料不一致的情形,A賬戶減去100元,而B賬戶增加100元操作失敗,系統將無故丟失100元。
- 一致性( consistency ):
(國內很多網站上對一致性的闡述有誤,具體你可以參考Wikipedia對Consistency的闡述)
根據定義,一致性是指事務執行前後,資料從一個合法性狀態
變換到另外一個合法性狀態
。這種狀態是語義上的而不是語法上的,跟具體的業務有關。
那什麼是合法的資料狀態呢? 滿足預定的約束
的狀態就叫做合法的狀態。通俗一點,這狀態是由你自己來定義的(比如滿足現實世界中的約束)。滿足這個狀態,資料就是一致的,不滿足這個狀態,資料就是不一致的! 如果事務中的某個操作失敗了,系統就會自動撤銷當前正在執行的事務,返回到事務操作之前的狀態。
舉例1:A賬戶有200元,轉賬300元出去,此時A賬戶餘額為-100元。你自然就發現了此時資料是不一致的,為什麼呢?因為你定義了一個狀態,餘額這列必須>=0。
舉例2:A賬戶200元,轉賬50元給B賬戶,A賬戶的錢扣了,但是B賬戶因為各種意外,餘額並沒有增加。你也知道此時資料是不一致的,為什麼呢?因為你定義了一個狀態,要求A+B的總餘額必須不變。
舉例3:在資料表中我們將姓名
欄位設定為唯一性約束
,這時當事務進行提交或者事務發生回滾的時候,如果資料表中的姓名不唯一,就破壞了事務的一致性要求。
- 隔離性( isolation )
事務的隔離性庭指一個事務的執行不能被其他事務干擾
,即一個事務內部的操作及使用的資料對併發
的其他事務是隔離的,併發執行的各個事務之間不能互相干擾。
如果無法保證隔離性會怎麼樣?假設A賬戶有200元,B賬戶o元。A賬戶往B賬戶轉賬兩次,每次金額為50元,分別在兩個事務中執行。如果無法保證隔離性,會出現下面的情形:
UPDATE accounts SET money = money - 50 WHERE NAME = 'AA' ;
UPDATE accounts SET money = money + 50 WHERE NAME = 'BB';
- 永續性(durability):
永續性是指一個事務一旦被提交,它對資料庫中資料的改變就是永久性的
,接下來的其他操作和資料庫故障不應該對其有任何影響。
永續性是透過事務日誌
來保證的。日誌包括了重做日誌
和回滾日誌
。當我們透過事務對資料進行修改的時候,首先會將資料庫的變化資訊記錄到重做日誌中,然後再對資料庫中對應的行進行修改。這樣做的好處是,即使資料庫系統崩潰,資料庫重啟後也能找到沒有更新到資料庫系統中的重做日誌,重新執行,從而使事務具有永續性。
總結
ACID是事務的四大特性,在這四個特性中,原子性是基礎,隔離性是手段,一致性是約束條件,而永續性是我們的目的。資料庫事務,其實就是資料庫設計者為了方便起見,把需要保證
原子性
、隔離性
、一致性
和永續性
的一個或多個資料庫操作稱為一個事務。
1.4 事務的狀態
我們現在知道事務
是一個抽象的概念,它其實對應著一個或多個資料庫操作,MySQL根據這些操作所執行的不同階段把事務
大致劃分成幾個狀態:
- 活動的(active)
事務對應的資料庫操作正在執行過程中時,我們就說該事務處在活動的
狀態。
- 部分提交的(partially committed)
當事務中的最後一個操作執行完成,但由於操作都在記憶體中執行,所造成的影響並沒有重新整理到磁碟時
,我們就說該事務處在部分提交的
狀態。
- 失敗的(failed)
當事務處在活動的
或者部分提交的
狀態時,可能遇到了某些錯誤(資料庫自身的錯誤、作業系統錯誤或者直接斷電等)而無法繼續執行,或者人為的停止當前事務的執行,我們就說該事務處在失敗的
狀態。
- 中止的(aborted)
如果事務執行了一部分而變為失敗的
狀態,那麼就需要把已經修改的事務中的操作還原到事務執行前的狀態。換句話說,就是要撤銷失敗事務對當前資料庫造成的影響。我們把這個撤銷的過程稱之為回滾
。當回滾
操作執行完畢時,也就是資料庫恢復到了執行事務之前的狀態,我們就說該事務處在了中止的
狀態。
舉例:
UPDATE accounts SET money = money - 50 WHERE NAME = 'AA';
UPDATE accounts SET money = money + 50 WHERE NAME = 'BB';
- 提交的(committed)
當一個處在部分提交的
狀態的事務將修改過的資料都同步到磁碟
上之後,我們就可以說該事務處在了提交的
狀態。
一個基本的狀態轉換圖如下所示:
圖中可見,只有當事務處於提交的
或者中止的
狀態時,一個事務的生命週期才算是結束了。對於已經提交的事務來說,該事務對資料庫所做的修改將永久生效,對於處於中止狀態的事務,該事務對資料庫所做的所有修改都會被回滾到沒執行該事務之前的狀態。
2.如何使用事務
使用事務有兩種方式,分別為顯式事務
和隱式事務
。
2.1 顯式事務
步驟1:start transtaction
或者BEGIN
,作用是顯示開啟一個事務。
start transtaction;-- 真實寫的時候,關鍵字都建議大寫,此處是筆記,便於觀看故小寫。
-- ..DML操作,資料庫修改語言
-- data modify language
commit;
-- 或者
begin;
-- ..DML操作,資料庫修改語言
-- data modify language
commit;
start transtaction
語句相較於begin
特別之處在於,後邊能跟隨幾個修飾符
:
① read only
:標識當前事務是一個只讀事務
,也就是屬於該事務的資料庫操作只能讀取資料,而不能修改資料。
補充:只讀事務中只是不允許修改那些其他事務也能訪問到的表中的資料,對於臨時表來說(我們使用
CREATE TMEPORARY TABLE
建立的表),由於它們只能在當前會話中可見,所以只讀事務其實也是可以對臨時表進行增、刪、改操作的。
② read write
:預設情況
;標識當前事務是一個可讀可寫
事務,也就是當前事務下的操作,可以讀取資料,也可以寫(修改)資料。
③ with consistent snapshot
:啟動一致性讀。
START TRANSACTION WITH CONSISTENT SNAPSHOT
是SQL語句的一部分,主要用於開啟一個事務,並且這個事務將使用一致性快照(consistent snapshot)的隔離級別。在資料庫管理系統中,事務的隔離級別定義了事務之間如何互動以及資料的一致性如何被維護。一致性快照是一種讀取已提交(Read Committed)隔離級別的變體,但它提供了一種更穩定的檢視,使事務能夠看到在其開始時一致的資料狀態,而不是實時的資料變化。當你在一個事務中使用
WITH CONSISTENT SNAPSHOT
選項時,該事務將看到在它開始時刻所有已經提交的事務所反映出來的資料狀態。這意味著,即使在事務執行期間有其他事務對資料進行了修改並提交,當前事務仍然會看到開始時刻的資料狀態,而不是這些實時的更新。這有助於避免某些型別的併發問題,如幻讀(Phantom Reads),即在兩次查詢之間,由於其他事務插入了新行而出現額外的行。這種機制對於需要穩定資料檢視的複雜查詢或批處理操作特別有用,因為它可以減少鎖的競爭,提高併發效能,同時保持資料的一致性和事務的隔離性。
然而,值得注意的是,不同資料庫系統可能對
WITH CONSISTENT SNAPSHOT
的實現和支援程度有所不同。例如,PostgreSQL 自動為每個事務提供一致性快照,而不需要顯式指定。但在其他一些資料庫系統中,如SQL Server,你可能需要明確地使用這個選項來控制事務的隔離級別和行為。來自,通義千問
比如:
start transaction read only;#開啟只讀事務
start transaction read write,with consistent snapshot;#開啟只讀,和一致性讀事務
#注意,read only 和 read write事務都可以和一致性讀事務,同時使用,但是其二者不能同時使用
READ ONLY
和READ WRITE
是用來設定所謂的事務訪問模式
的,就是以只讀還是讀寫的方式來訪問資料庫中的資料,一個事務的訪問模式不能同時既設定為只讀
的也設定為讀寫
的,所以不能同時把READ ONLY
和READ WRITE
放到START TRANSACTION
語句後邊。- 如果使用
start xx語句
開啟且不顯式指定事務的訪問模式,那麼該事務的訪問模式就是讀寫
模式。
步驟2:一系列事務中的操作(主要是DML,不包括DDL) DDL(Data Definition Language)
步驟3:提交事務或中止事務(即回滾事務)
#提交事務。當提交事務後,對資料庫的修改是永久性的
commit;
#回滾事務,即撤銷正在進行的所有沒有提交的修改
rollback;
rollback to savepoint;#將事務回滾到,當前事務中的儲存點
-- 在事務中建立儲存點,方便後續對儲存點進行回滾,一個事務中可以存在多個儲存點
savepoint 儲存點名稱;
-- 刪除某個儲存點
release savepoint 儲存點名稱;
2.2 隱式事務
MySQL中有一個系統變數autocommit
。
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
1 row in set (0.00 sec)
預設情況下,如果我們不顯式的使用START TRANSACTION
或者BEGIN
語句開啟一個事務,那麼每一條語句都算是一個獨立的事務,這種特性稱之為事務的自動提交
。也就是說,不以START TRANSACTION
或者BEGIN
語句顯式的開啟一個事務,那麼下邊這兩條語句就相當於放到兩個獨立的事務中去執行:
UPDATE account SET balance = balance - 10 WHERE id = 1;
UPDATE account SET balance = balance + 10 WHERE id = 2;
當然,如果關閉這種自動提交功能,可以使用下邊兩種方法之一。
- 顯式的的使用
START TRANSACTION
或者BEGIN
語句開啟一個事務。這樣在本次事務提交或者回滾前會暫時關閉掉自動提交的功能。 - 把系統變數
autocommit
的值設定為OFF
,就像這樣。
SET autocommit = 'OFF';-- 會話級別
SET autocommit = 0;-- 會話級別
這樣的話,我們寫入的多條語句就算是屬於同一個事務了,直到我們顯示的寫出commit
語句來吧這個事務提交掉,或者顯示的寫出ROLLBACK
語句來把這個事務回滾掉。
Oracle資料庫,預設不自動,commit,而MySQL中,有自動提交。
2.3 隱式提交事務的情況
- 資料定義語言(Data definition language,縮寫為:DDL)
資料庫物件,指的就是資料庫
、表
、檢視
、儲存過程
等結構。當我們使用CREATE
、ALTER
、DROP
等語句去修改資料庫物件時,就會隱式的提交前邊語句所屬於的事務。即:
BEGIN;
SELECT ...
UPDATE ...
... #事務的其他語句
create table ... -- 此語句會隱式的提交前邊語句所屬的事務
- 隱式使用或修改mysql資料庫中的表
當我們使用ALTER USER
、CREATE USER
、DROP USER
、GRANT
、RENAME USER
、REVOKE
、SET PASSWORD
等語句時也會隱式的提交前邊語句所屬於的事務。
- 事務控制或關於鎖定的語句
① 當我們在一個事務還沒提交或者回滾時就又使用START TRANSACTION
或者BEGIN
語句開啟了另一個事務時,會隱式的提交
上一個事務。即:
② 當前的autocommit
系統變數的值為OFF
,我們手動把它調為ON
時,也會隱式的提交
前邊語句所屬的事務。
③ 使用LOCK TABLES
、UNLOCK TABLES
等關於鎖定的語句也會隱式的提交
前邊語句所屬的事務。LOCK
和UNLOCK
語句,後面章節會講解。
- 載入資料的語句
使用LOAD DATA
語句來批次往資料庫中匯入資料時,也會隱式的提交
前邊語句所屬的事務。
- 關於MySQL複製的一些語句
使用START SLAVE
、STOP SLAVE
、RESET SLAVE
、CHANGE MASTER TO
等語句時會隱式的提交前邊語句所屬的事務。後續章節。
- 其他的一些語句
使用ANALYZE TABLE、CACHE INDEX、CHECK TABLE、FLUSH、LOAD INDEX INTO CACHE 、OPTIMIZE TABLE、REPAIR TABLE、RESET等語句也會隱式的提交前邊語句所屬的事務。
2.4 使用舉例
略
3.事務隔離級別
MysQL是一個客戶端/伺服器
架構的軟體,對於同一個伺服器來說,可以有若干個客戶端與之連線,每個客戶端與伺服器連線上之後,就可以稱為一個會話(Session
)。每個客戶端都可以在自己的會話中向伺服器發出請求語句,一個請求語句可能是某個事務的一部分,也就是對於伺服器來說可能同時處理多個事務。事務有隔離性
的特性,理論上在某個事務對某個資料進行訪問
時,其他事務應該進行排隊
,當該事務提交之後,其他事務才可以繼續訪問這個資料。但是這樣對效能影響太大
,我們既想保持事務的隔離性,又想讓伺服器在處理訪問同一資料的多個事務時效能儘量高些
,那就看二者如何權衡取捨了。
3.1 資料準備
我們需要建立一個表:
CREATE TABLE student (
studentno INT,
name VARCHAR(20),
class varchar(20),
PRIMARY KEY (studentno)
) Engine=InnoDB CHARSET=utf8;
然後向這個表裡插入一條資料:
INSERT INTO student VALUES(1, '小谷', '1班');
mysql> select * from student;
+-----------+--------+-------+
| studentno | name | class |
+-----------+--------+-------+
| 1 | 小谷 | 1班 |
+-----------+--------+-------+
1 row in set (0.00 sec)
3.2 資料併發問題
針對事務的隔離性和併發性,我們怎麼做取捨呢?先看一下訪問相同資料的事務在不保證序列執行
(也就是執行完一個再執行另一個)的情況下可能會出現哪些問題:
1.髒寫(Dirty Write
)
對於兩個事務 Session A、Session B,如果事務Session A修改了
另一個未提交
事務Session B修改過
的資料,那就意味著發生了髒寫
。
2.髒讀( Dirty Read
)
對於兩個事務 Session A、Session B,Session A讀取
了已經被 Session B更新
但還沒有被提交
的欄位。之後若 Session B回滾
,Session A讀取
的內容就是臨時且無效
的。
Session A和Session B各開啟了一個事務,Session B中的事務先將studentno列為1的記錄的name列更新為'張三',然後Session A中的事務再去查詢這條studentno為1的記錄,如果讀到列name的值為'張三',而Session B中的事務稍後進行了回滾,那麼Session A中的事務相當於讀到了一個不存在的資料,這種現象就稱之為髒讀
。
3.不可重複讀( Non-Repeatable Read
)
對於兩個事務Session A、Session B,Session A讀取
了一個欄位,然後 Session B更新
了該欄位。 之後Session A再次讀取
同一個欄位, 值就不同 了。那就意味著發生了不可重複讀。
我們在Session B中提交了幾個隱式事務
(注意是隱式事務,意味著語句結束事務就提交了),這些事務都修改了studentno列為1的記錄的列name的值,每次事務提交之後,如果Session A中的事務都可以檢視到最新的值,這種現象也被稱之為不可重複讀
。
4.幻讀( Phantom
)
對於兩個事務Session A、Session B, Session A 從一個表中讀取
了一個欄位, 然後 Session B 在該表中插入
了一些新的行。 之後, 如果 Session A再次讀取
同一個表, 就會多出幾行。那就意味著發生了幻讀。
Session A中的事務先根據條件 studentno > 0這個條件查詢表student,得到了name列值為'張三'的記錄;之後Session B中提交了一個隱式事務
,該事務向表student中插入了一條新記錄;之後Session A中的事務再根據相同的條件 studentno > 0查詢表student,得到的結果集中包含Session B中的事務新插入的那條記錄,這種現象也被稱之為幻讀
。我們把新插入的那些記錄稱之為幻影記錄
。
注意,這裡的4個問題,只是在事務併發訪問可能會出現的問題,在實際的使用中,要根據自身專案對於,資料一致性的要求,來考慮,是否要全部避免這些的問題。這也是,MySQL為什麼會出現隔離級別,來控制,避免這定義的標準問題中的某幾個,而不是直接預設一個隔離級別,避免這些所有的問題的原因。
3.3 SQL中的四種隔離級別
上面介紹了幾種併發事務執行過程中可能遇到的一些問題,這些問題有輕重緩急之分,我們給這些問題按照嚴重性來排一下序:
髒寫 > 髒讀 > 不可重複讀 > 幻讀
我們願意捨棄一部分隔離性來換取一部分效能在這裡就體現在:設立一些隔離級別,隔離級別越低,併發問題發生的就越多。SQL標準
中設立了4個隔離級別
:
READ UNCOMMITTED
:讀未提交,在該隔離級別,所有事務都可以看到其他未提交事務的執行結果。不能避免髒讀、不可重複讀、幻讀。READ COMMITTED
:讀已提交,它滿足了隔離的簡單定義:一個事務只能看見已經提交事務所做的改變。這是大多數資料庫系統的預設隔離級別(但不是MySQL預設的)。可以避免髒讀,但不可重複讀、幻讀問題仍然存在。REPEATABLE READ
:可重複讀,事務A在讀到一條資料之後,此時事務B對該資料進行了修改並提交,那麼事務A再讀該資料,讀到的還是原來的內容。可以避免髒讀、不可重複讀,但幻讀問題仍然存在。這是MySQL的預設隔離級別。SERIALIZABLE
:可序列化,確保事務可以從一個表中讀取相同的行。在這個事務持續期間,禁止其他事務對該表執行插入、更新和刪除操作。所有的併發問題都可以避免,但效能十分低下。能避免髒讀、不可重複讀和幻讀。
SQL標準
中規定,針對不同的隔離級別,併發事務可以發生不同嚴重程度的問題,具體情況如下:
髒寫
怎麼沒涉及到?因為髒寫這個問題太嚴重了,不論是哪種隔離級別,都不允許髒寫的情況發生。
不同的隔離級別有不同的現象,並有不同的鎖和併發機制,隔離級別越高,資料庫的併發效能就越差,4種事務隔離級別與併發效能的關係如下:
3.4 MySQL支援的四種隔離級別
MySQL的預設隔離級別為REPEATABLE READ,我們可以手動修改一下事務的隔離級別。
# 檢視隔離級別,MySQL 5.7.20的版本之前:
mysql> SHOW VARIABLES LIKE 'tx_isolation';
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)
# MySQL 5.7.20版本之後,引入transaction_isolation來替換tx_isolation
# 檢視隔離級別,MySQL 5.7.20的版本及之後:
mysql> SHOW VARIABLES LIKE 'transaction_isolation';
+-----------------------+-----------------+
| Variable_name | Value |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.02 sec)
#或者不同MySQL版本中都可以使用的:
SELECT @@transaction_isolation;
3.5 設定隔離級別
SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL 隔離級別;
#其中,隔離級別格式:
> READ UNCOMMITTED
> READ COMMITTED
> REPEATABLE READ
> SERIALIZABLE
#或者
SET [GLOBAL|SESSION] TRANSACTION_ISOLATION = '隔離級別' -- 宋紅康老師推薦這種方式
#其中,隔離級別格式:
> READ-UNCOMMITTED -- 注意 '-'符號連線
> READ-COMMITTED
> REPEATABLE-READ
> SERIALIZABLE
對於GLOBAL | SESSION的影響
- 使用
GLOBAL
關鍵字(在全域性範圍影響):
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE; #臨時全域性
#或
SET GLOBAL TRANSACTION_ISOLATION = 'SERIALIZABLE';
-
當前已經存在的會話無效
-
只對執行完該語句之後產生的會話起作用
-
使用 SESSION 關鍵字(在會話範圍影響):
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
#或
SET SESSION TRANSACTION_ISOLATION = 'SERIALIZABLE';
- 對當前會話的所有後續的事務有效
- 如果在事務之間執行,則對後續的事務有效
- 該語句可以在已經開啟的事務中間執行,但不會影響當前正在執行的事務
小結:
資料庫規定了多種事務隔離級別,不同隔離級別對應不同的干擾程度,隔離級別越高,資料一致性就越好,但併發性越弱。
全域性修改
TRANSACTION_ISOLATION=REPEATABLE-READ #注意是-不是空格
3.6 不同隔離級別舉例
讀未提交之髒讀
設定隔離級別為讀未提交:
事務1和事務2的執行流程如下:
阻塞原因,是加了鎖。在後續MVCC章節中對講到,MVCC(Multiversion Concurrency Control) 多版本併發控制
演示2:讀已提交
演示3:可重複讀級別
設定隔離級別為可重複讀,事務的執行流程如下:
幻讀問題
這裡要靈活的理解讀取
的意思,第一次select是讀取,第二次的insert其實也屬於隱式的讀取,只不過是在mysql的機制中讀取的,插入資料也是要先讀取一下有沒有主鍵衝突才能決定是否執行插入。
幻讀,並不是說兩次讀取獲取的結果集不同,幻讀側重的方面是某一次的select 操作得到的結果所表徵的資料狀態無法支撐後續的業務操作。更為具體一些: select 某記錄是否存在,不存在,準備插入此記錄,但執行insert時發現此記錄已存在,無法插入,此時就發生了幻讀。
在RR(可重複讀)隔離級別下,step1、step2是會正常執行的,step3則會報錯主鍵衝突,對於事務1的業務來說是執行失敗的,這裡事務1就是發生了幻讀,因為事務1在step1中讀取的資料狀態並不能支撐後續的業務操作,事務1:“見鬼了,我剛才讀到的結果應該可以支援我這樣操作才對啊,為什麼現在不可以”。事務1不敢相信的又執行了step4,發現和setp1讀取的結果是一樣的(RR下的MVCC機制)。此時,幻讀無疑已經發生,事務1無論讀取多少次,都查不到id =3的記錄,但它的確無法插入這條他透過讀取來認定不存在的記錄(此資料已被事務2插入),對於事務1來說,它幻讀了。
其實RR也是可以避免幻讀的,透過對select操作手動加行X鎖(獨佔鎖)
(SELECT ...FOR UPDATE這也正是SERIALIZABLE隔離級別下會隱式為你做的事情)。同時,即便當前記錄不存在,比如id = 3是不存在的,當前事務也會獲得一把記錄鎖(因為InnoDB的行鎖鎖定的是索引,故記錄實體存在與否沒關係,存在就加行X鎖,不存在就加間隙鎖
),其他事務則無法插入此索引的記錄,故杜絕了幻讀。
在SERIALIZABLE隔離級別
下,step1執行時是會隱式的新增行(X)鎖
/gap(X)鎖
的,從而step2會被阻塞,step3會正常執行,待事務1提交後,事務2才能繼續執行(主鍵衝突執行失敗),對於事務1來說業務是正確的,成功的阻塞扼殺了擾亂業務的事務2,對於事務1來說他前期讀取的結果是可以支撐其後續業務的。
所以MySQL的幻讀並非什麼讀取兩次返回結果集不同,而是事務在插入事先檢測不存在的記錄時,驚奇的發現這些資料已經存在了,之前的檢測讀獲取到的資料如同鬼影一般。
這裡,只是丟擲這些問題,後續章節,有這些內容的解釋。
4.事務的常見分類
從事務理論的角度來看,可以把事務分為以下幾種型別:
- 扁平事務(Flat Transactions)
- 帶有儲存點的扁平事務(Flat Transactions with Savepoints)
- 鏈事務(Chained Transactions)
- 巢狀事務(Nested Transactions)
- 分散式事務(Distributed Transactions)
只是為了記錄自己的學習歷程,且本人水平有限,不對之處,請指正。