首頁  >  文章  >  資料庫  >  MySQL詳解之事務隔離機制與實作原理

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

WBOY
WBOY轉載
2022-11-14 16:29:332003瀏覽

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

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

推薦學習:mysql影片教學

#一、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视频教程

以上是MySQL詳解之事務隔離機制與實作原理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.im。如有侵權,請聯絡admin@php.cn刪除