MySQL詳解之事務隔離機制與實現原理

2022-11-14 18:02:32
本篇文章給大家帶來了關於的相關知識, 其中主要介紹了MySQL事務的使用和其存在長事務的風險、MySQL 的事務及其特性,並行事務帶來的問題、事務的隔離級別與演示,單版本控制鎖以及多版本並行控制 MVCC等內容,下面一起來看一下,希望對大家有幫助。

程式設計師必備介面測試偵錯工具:

推薦學習:

一、MySQL事務使用

1、什麼是事務

事務是作為單個邏輯工作單元執行的一系列操作。這些操作要麼全部,要麼沒有,是一個不可分割的工作單元。

例如,購買東西支付的過程中會有一系列操作,如查詢餘額、加減、更新餘額。這些操作必須是同時的。否則,顯示你支付成功,但是系統沒有收到錢

在MySQL中,事務支援是在引擎層實現的,MyISAM引擎不支援事務

2、事務的四個特性

要成為事務,邏輯工作單元必須滿足關聯式資料庫管理系統中的四個特徵。

即所謂的ACID:原子性、一致性、隔離性、永續性。

原子性:事務的所有操作要麼完成要麼未完成,不會在中間階段結束。

一致性:在事務之前和之後,資料庫的完整性限制不會被打破。

隔離性:當多個事務同時存取資料庫中的同一資料時,將顯示關係。

永續性:事務完成後,事務所做的更改將持久儲存,不會丟失。

ACID 需要通過 Redo 和 Undo 紀錄檔來保證。MySQL紀錄檔系統詳解:(後續補充)

3、MySQL事務使用

MySQL 的事務啟動方式有以下2種:

3.1、顯式啟動事務語句

begin 或 start transaction。配套的提交語句是 commit,回滾語句是 rollback。

BEGIN -- 開啟事務
START TRANSACTION -- 開啟事務

INSERT INTO fork_business_detail VALUES ( 4, '123', '123', '123004', '2022-11-12 17:17:29', '1', '2022-11-12 17:17:37', '1' );

COMMIT -- 提交事務

ROLLBACK -- 回滾事務
登入後複製

3.2、關閉自動提交

set autocommit=0,這個命令會將這個執行緒的自動提交關掉。意味著如果你只執行一個 select 語句,這個事務就啟動了,而且並不會自動提交。這個事務持續存在直到你主動執行 commit 或 rollback 語句,或者斷開連線。(不建議使用!)

set autocommit=0 -- 關閉自動提交

INSERT INTO fork_business_detail VALUES ( 4, '123', '123', '123004', '2022-11-12 17:17:29', '1', '2022-11-12 17:17:37', '1' );

COMMIT -- 提交事務

ROLLBACK -- 回滾事務
登入後複製

二、MySQL事務隔離性與隔離機制

當在資料庫上同時執行多個事務(可以理解為多工、並行場景)時,可能會發生髒讀、不可重複讀和幻讀。

1、四種隔離級別

為了解決這些問題,MySQL 引入了「隔離級別」的概念。

隔離級別越高,效率就越低,很多時候,我們必須在兩者之間找到平衡。SQL標準的事務隔離級別包括:讀(取)未提交(read uncommitted)、讀(取)已提交(read committed)、可重複讀取(repeatable read)和序列化(serializable )。

讀未提交RU,Read Uncommitted),它可以讀取事務的中間過程。它違反了ACID特性,並且存在髒讀取的問題。因此基本上不被使用,可以被忽略。

讀已提交RC,Read Committed),這意味著,如果已經提交了其他事務,我們可以看到這也是最常用的級別。然而,由於一些歷史原因,RC可能在生產環境中使用不多。

可重複讀RR,Repeatable Read)是目前使用最廣泛的級別。它的特點是間隙鎖定,這仍然是預設級別。在這個級別,死鎖、低並行和其他問題經常發生。

序列化(serializable ),不是多版本實現,而是單版本實現,因為它的所有實現都是通過鎖實現的。基本上不被使用,可以被忽略。

2、並行事務引起的問題

髒讀:事務A讀取事務B更新的資料,然後B回滾,因此A讀取的資料是髒的(實際上不應該存在的資料)

不可重複讀:事務A多次讀取相同的資料。事務B在事務A多次讀取的過程中更新並提交資料,導致事務A多次捕獲同一資料時結果不一致。

一個事務讀取到其他事務已提交的資料導致前後兩次讀取資料不一樣的情況

幻讀:A查出來資料,此時B提交,A再次查同一資料時結果不一致。一個事務前後兩次讀取的資料不一致,是因為其他事務插入資料導致的事務並行情況

不可重複讀和幻讀很容易混淆,不可重複讀側重於修改,而幻讀側重於新增或刪除。要解決不可重複讀取的問題,只需要符合條件的行,而要解決幻讀問題需要鎖表

3、隔離級別問題剖析與演示

3.1 檢視mysql事務隔離級別

SELECT @@transaction_isolation; -- 檢視mysql事務隔離級別
SELECT @@tx_isolation;          -- 檢視mysql事務隔離級別
登入後複製

3.2、髒讀問題

將事務隔離級別修改為讀未提交,可以看到,事務還沒有提交,這時候去查詢這條資料,發現資料已經可見了。

set session transaction isolation level read uncommitted; -- 設定成讀未提交
SELECT @@tx_isolation;          -- 檢視mysql事務隔離級別

START TRANSACTION -- 事務A
INSERT INTO fork_business_detail VALUES ( 4, '123', '123', '123004', '2022-11-12 17:17:29', '1', '2022-11-12 17:17:37', '1' );
ROLLBACK

select * from fork_business_detail where id= 4 -- 事務B
登入後複製

3.3、不可重複讀

一個事務讀取到其他事務已提交的資料導致前後兩次讀取資料不一樣的情況。

select * from fork_business_detail where id= 4;

BEGIN; -- 開啟事務
select * from fork_business_detail where id= 4;
UPDATE fork_business_detail set SUB_ODR_ID=123004 where id= 4;
COMMIT;

select * from fork_business_detail where id= 5;
登入後複製

三、MySQL事務實現原理

1、單版本控制——鎖

serializable ,使用鎖獨佔方式來確保只有一個版本時事務被隔離,因此鎖可以理解為單版本控制。

在MySQL事務中,鎖的實現與隔離級別有關。在RR(Repeatable Read)隔離級別下,MySQL使用間隙鎖來防止以並行性為代價寫入資料,以解決虛擬讀取的問題。

這種型別的鎖通常會導致死鎖,因為它沒有足夠的並行性和許多衝突。現在流行的Row模式可以避免許多衝突甚至死鎖,因此建議預設使用Row+RC(Read Committed)模式隔離級別,這可以大大提高資料庫的讀寫並行性。

2、多版本控制MVCC

多版本控制,也稱為MVCC,是指資料的多版本處理,以實現資料庫中的高度並行資料存取,以及事務的可見性,以確保事務可以看到其應該看到的資料版本。

如何生成多個版本?

每次修改資料庫時,撤消( Undo log)紀錄檔都會記錄當前修改記錄的事務號和修改前資料狀態的儲存地址(即ROLL_PTR),以便在必要時回滾舊資料版本。

例如,讀取事務查詢當前記錄,但最近的事務尚未提交。根據原子性,讀取事務無法看到最新的資料,但您可以在回滾段中找到舊版本資料,從而生成多個版本。

多版本控制巧妙地將獨佔和獨佔的稀有資源轉換為並行,大大提高了資料庫吞吐量和讀/寫效能。

推薦學習:

以上就是MySQL詳解之事務隔離機制與實現原理的詳細內容,更多請關注TW511.COM其它相關文章!