自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一文說盡MySQL事務(wù)及ACID特性的實(shí)現(xiàn)原理

原創(chuàng)
數(shù)據(jù)庫 MySQL
事務(wù)是 MySQL 等關(guān)系型數(shù)據(jù)庫區(qū)別于 NoSQL 的重要方面,是保證數(shù)據(jù)一致性的重要手段。

【51CTO.com原創(chuàng)稿件】事務(wù)是 MySQL 等關(guān)系型數(shù)據(jù)庫區(qū)別于 NoSQL 的重要方面,是保證數(shù)據(jù)一致性的重要手段。

本文將首先介紹 MySQL 事務(wù)相關(guān)的基礎(chǔ)概念,然后介紹事務(wù)的 ACID 特性,并分析其實(shí)現(xiàn)原理。MySQL 博大精深,文章疏漏之處在所難免,歡迎批評(píng)指正。

MySQL 事務(wù)基礎(chǔ)概念

事務(wù)(Transaction)是訪問和更新數(shù)據(jù)庫的程序執(zhí)行單元;事務(wù)中可能包含一個(gè)或多個(gè) sql 語句,這些語句要么都執(zhí)行,要么都不執(zhí)行。

作為一個(gè)關(guān)系型數(shù)據(jù)庫,MySQL 支持事務(wù),本文介紹基于 MySQL 5.6。首先回顧一下 MySQL 事務(wù)的基礎(chǔ)知識(shí)。

邏輯架構(gòu)和存儲(chǔ)引擎

 

如上圖所示,MySQL 服務(wù)器邏輯架構(gòu)從上往下可以分為三層:

  • 第一層:處理客戶端連接、授權(quán)認(rèn)證等。
  • 第二層:服務(wù)器層,負(fù)責(zé)查詢語句的解析、優(yōu)化、緩存以及內(nèi)置函數(shù)的實(shí)現(xiàn)、存儲(chǔ)過程等。
  • 第三層:存儲(chǔ)引擎,負(fù)責(zé) MySQL 中數(shù)據(jù)的存儲(chǔ)和提取。MySQL 中服務(wù)器層不管理事務(wù),事務(wù)是由存儲(chǔ)引擎實(shí)現(xiàn)的。

MySQL 支持事務(wù)的存儲(chǔ)引擎有 InnoDB、NDB Cluster 等,其中 InnoDB 的使用最為廣泛;其他存儲(chǔ)引擎不支持事務(wù),如 MyIsam、Memory 等。

如無特殊說明,后文中描述的內(nèi)容都是基于 InnoDB。

提交和回滾

典型的 MySQL 事務(wù)是如下操作的:

  1. start transaction
  2. ……  #一條或多條sql語句 
  3. commit

其中 start transaction 標(biāo)識(shí)事務(wù)開始,commit 提交事務(wù),將執(zhí)行結(jié)果寫入到數(shù)據(jù)庫。

如果 sql 語句執(zhí)行出現(xiàn)問題,會(huì)調(diào)用 rollback,回滾所有已經(jīng)執(zhí)行成功的 sql 語句。當(dāng)然,也可以在事務(wù)中直接使用 rollback 語句進(jìn)行回滾。

自動(dòng)提交

MySQL 中默認(rèn)采用的是自動(dòng)提交(autocommit)模式,如下所示:

 

在自動(dòng)提交模式下,如果沒有 start transaction 顯式地開始一個(gè)事務(wù),那么每個(gè) sql 語句都會(huì)被當(dāng)做一個(gè)事務(wù)執(zhí)行提交操作。

通過如下方式,可以關(guān)閉 autocommit;需要注意的是,autocommit 參數(shù)是針對(duì)連接的,在一個(gè)連接中修改了參數(shù),不會(huì)對(duì)其他連接產(chǎn)生影響。

 

如果關(guān)閉了 autocommit,則所有的 sql 語句都在一個(gè)事務(wù)中,直到執(zhí)行了 commit 或 rollback,該事務(wù)結(jié)束,同時(shí)開始了另外一個(gè)事務(wù)。

特殊操作

在 MySQL 中,存在一些特殊的命令,如果在事務(wù)中執(zhí)行了這些命令,會(huì)馬上強(qiáng)制執(zhí)行 commit 提交事務(wù);如 DDL 語句(create table/drop table/alter/table)、lock tables 語句等等。

不過,常用的 select、insert、update 和 delete 命令,都不會(huì)強(qiáng)制提交事務(wù)。

ACID 特性

ACID 是衡量事務(wù)的四個(gè)特性:

  • 原子性(Atomicity,或稱不可分割性)
  • 一致性(Consistency)
  • 隔離性(Isolation)
  • 持久性(Durability)

按照嚴(yán)格的標(biāo)準(zhǔn),只有同時(shí)滿足 ACID 特性才是事務(wù);但是在各大數(shù)據(jù)庫廠商的實(shí)現(xiàn)中,真正滿足 ACID 的事務(wù)少之又少。

例如 MySQL 的 NDB Cluster 事務(wù)不滿足持久性和隔離性;InnoDB 默認(rèn)事務(wù)隔離級(jí)別是可重復(fù)讀,不滿足隔離性;Oracle 默認(rèn)的事務(wù)隔離級(jí)別為 READ COMMITTED,不滿足隔離性……

因此與其說 ACID 是事務(wù)必須滿足的條件,不如說它們是衡量事務(wù)的四個(gè)維度。

下面將詳細(xì)介紹 ACID 特性及其實(shí)現(xiàn)原理,為了便于理解,介紹的順序不是嚴(yán)格按照 A-C-I-D。

ACID 特性及其實(shí)現(xiàn)原理

原子性

定義

原子性是指一個(gè)事務(wù)是一個(gè)不可分割的工作單位,其中的操作要么都做,要么都不做。

如果事務(wù)中一個(gè) sql 語句執(zhí)行失敗,則已執(zhí)行的語句也必須回滾,數(shù)據(jù)庫退回到事務(wù)前的狀態(tài)。

實(shí)現(xiàn)原理:undo log

在說明原子性原理之前,首先介紹一下 MySQL 的事務(wù)日志。MySQL 的日志有很多種,如二進(jìn)制日志、錯(cuò)誤日志、查詢?nèi)罩?、慢查詢?nèi)罩镜取?/p>

此外 InnoDB 存儲(chǔ)引擎還提供了兩種事務(wù)日志:

  • redo log(重做日志)
  • undo log(回滾日志)

其中 redo log 用于保證事務(wù)持久性;undo log 則是事務(wù)原子性和隔離性實(shí)現(xiàn)的基礎(chǔ)。

下面說回 undo log。實(shí)現(xiàn)原子性的關(guān)鍵,是當(dāng)事務(wù)回滾時(shí)能夠撤銷所有已經(jīng)成功執(zhí)行的 sql 語句。

InnoDB 實(shí)現(xiàn)回滾,靠的是 undo log:

  • 當(dāng)事務(wù)對(duì)數(shù)據(jù)庫進(jìn)行修改時(shí),InnoDB 會(huì)生成對(duì)應(yīng)的 undo log。
  • 如果事務(wù)執(zhí)行失敗或調(diào)用了 rollback,導(dǎo)致事務(wù)需要回滾,便可以利用 undo log 中的信息將數(shù)據(jù)回滾到修改之前的樣子。

undo log 屬于邏輯日志,它記錄的是 sql 執(zhí)行相關(guān)的信息。當(dāng)發(fā)生回滾時(shí),InnoDB 會(huì)根據(jù) undo log 的內(nèi)容做與之前相反的工作:

  • 對(duì)于每個(gè) insert,回滾時(shí)會(huì)執(zhí)行 delete。
  • 對(duì)于每個(gè) delete,回滾時(shí)會(huì)執(zhí)行 insert。
  • 對(duì)于每個(gè) update,回滾時(shí)會(huì)執(zhí)行一個(gè)相反的 update,把數(shù)據(jù)改回去。

以 update 操作為例:當(dāng)事務(wù)執(zhí)行 update 時(shí),其生成的 undo log 中會(huì)包含被修改行的主鍵(以便知道修改了哪些行)、修改了哪些列、這些列在修改前后的值等信息,回滾時(shí)便可以使用這些信息將數(shù)據(jù)還原到 update 之前的狀態(tài)。

持久性

定義

持久性是指事務(wù)一旦提交,它對(duì)數(shù)據(jù)庫的改變就應(yīng)該是永久性的。接下來的其他操作或故障不應(yīng)該對(duì)其有任何影響。

實(shí)現(xiàn)原理:redo log

redo log 和 undo log 都屬于 InnoDB 的事務(wù)日志。下面先聊一下 redo log 存在的背景。

InnoDB 作為 MySQL 的存儲(chǔ)引擎,數(shù)據(jù)是存放在磁盤中的,但如果每次讀寫數(shù)據(jù)都需要磁盤 IO,效率會(huì)很低。

為此,InnoDB 提供了緩存(Buffer Pool),Buffer Pool 中包含了磁盤中部分?jǐn)?shù)據(jù)頁的映射,作為訪問數(shù)據(jù)庫的緩沖:

  • 當(dāng)從數(shù)據(jù)庫讀取數(shù)據(jù)時(shí),會(huì)首先從 Buffer Pool 中讀取,如果 Buffer Pool 中沒有,則從磁盤讀取后放入 Buffer Pool。
  • 當(dāng)向數(shù)據(jù)庫寫入數(shù)據(jù)時(shí),會(huì)首先寫入 Buffer Pool,Buffer Pool 中修改的數(shù)據(jù)會(huì)定期刷新到磁盤中(這一過程稱為刷臟)。

Buffer Pool 的使用大大提高了讀寫數(shù)據(jù)的效率,但是也帶來了新的問題:如果 MySQL 宕機(jī),而此時(shí) Buffer Pool 中修改的數(shù)據(jù)還沒有刷新到磁盤,就會(huì)導(dǎo)致數(shù)據(jù)的丟失,事務(wù)的持久性無法保證。

于是,redo log 被引入來解決這個(gè)問題:當(dāng)數(shù)據(jù)修改時(shí),除了修改 Buffer Pool 中的數(shù)據(jù),還會(huì)在 redo log 記錄這次操作;當(dāng)事務(wù)提交時(shí),會(huì)調(diào)用 fsync 接口對(duì) redo log 進(jìn)行刷盤。

如果 MySQL 宕機(jī),重啟時(shí)可以讀取 redo log 中的數(shù)據(jù),對(duì)數(shù)據(jù)庫進(jìn)行恢復(fù)。

redo log 采用的是 WAL(Write-ahead logging,預(yù)寫式日志),所有修改先寫入日志,再更新到 Buffer Pool,保證了數(shù)據(jù)不會(huì)因 MySQL 宕機(jī)而丟失,從而滿足了持久性要求。

既然 redo log 也需要在事務(wù)提交時(shí)將日志寫入磁盤,為什么它比直接將 Buffer Pool 中修改的數(shù)據(jù)寫入磁盤(即刷臟)要快呢?

主要有以下兩方面的原因:

  • 刷臟是隨機(jī) IO,因?yàn)槊看涡薷牡臄?shù)據(jù)位置隨機(jī),但寫 redo log 是追加操作,屬于順序 IO。
  • 刷臟是以數(shù)據(jù)頁(Page)為單位的,MySQL 默認(rèn)頁大小是 16KB,一個(gè) Page 上一個(gè)小修改都要整頁寫入;而 redo log 中只包含真正需要寫入的部分,無效 IO 大大減少。

redo log 與 binlog

我們知道,在 MySQL 中還存在 binlog(二進(jìn)制日志)也可以記錄寫操作并用于數(shù)據(jù)的恢復(fù),但二者是有著根本的不同的。

作用不同:

  • redo log 是用于 crash recovery 的,保證 MySQL 宕機(jī)也不會(huì)影響持久性;
  • binlog 是用于 point-in-time recovery 的,保證服務(wù)器可以基于時(shí)間點(diǎn)恢復(fù)數(shù)據(jù),此外 binlog 還用于主從復(fù)制。

層次不同:

  • redo log 是 InnoDB 存儲(chǔ)引擎實(shí)現(xiàn)的,
  • 而 binlog 是 MySQL 的服務(wù)器層(可以參考文章前面對(duì) MySQL 邏輯架構(gòu)的介紹)實(shí)現(xiàn)的,同時(shí)支持 InnoDB 和其他存儲(chǔ)引擎。

內(nèi)容不同:

  • redo log 是物理日志,內(nèi)容基于磁盤的 Page。
  • binlog 是邏輯日志,內(nèi)容是一條條 sql。

寫入時(shí)機(jī)不同:

  • redo log 的寫入時(shí)機(jī)相對(duì)多元。前面曾提到,當(dāng)事務(wù)提交時(shí)會(huì)調(diào)用 fsync 對(duì) redo log 進(jìn)行刷盤;這是默認(rèn)情況下的策略,修改 innodb_flush_log_at_trx_commit 參數(shù)可以改變?cè)摬呗?,但事?wù)的持久性將無法保證。

除了事務(wù)提交時(shí),還有其他刷盤時(shí)機(jī):如 master thread 每秒刷盤一次 redo log 等,這樣的好處是不一定要等到 commit 時(shí)刷盤,commit 速度大大加快。

  • binlog 在事務(wù)提交時(shí)寫入。

隔離性

定義

與原子性、持久性側(cè)重于研究事務(wù)本身不同,隔離性研究的是不同事務(wù)之間的相互影響。

隔離性是指事務(wù)內(nèi)部的操作與其他事務(wù)是隔離的,并發(fā)執(zhí)行的各個(gè)事務(wù)之間不能互相干擾。

嚴(yán)格的隔離性,對(duì)應(yīng)了事務(wù)隔離級(jí)別中的 Serializable(可串行化),但實(shí)際應(yīng)用中出于性能方面的考慮很少會(huì)使用可串行化。

隔離性追求的是并發(fā)情形下事務(wù)之間互不干擾。簡(jiǎn)單起見,我們僅考慮最簡(jiǎn)單的讀操作和寫操作(暫時(shí)不考慮帶鎖讀等特殊操作)。

那么隔離性的探討,主要可以分為兩個(gè)方面:

  • (一個(gè)事務(wù))寫操作對(duì)(另一個(gè)事務(wù))寫操作的影響:鎖機(jī)制保證隔離性。
  • (一個(gè)事務(wù))寫操作對(duì)(另一個(gè)事務(wù))讀操作的影響:MVCC 保證隔離性。

鎖機(jī)制

首先來看兩個(gè)事務(wù)的寫操作之間的相互影響。隔離性要求同一時(shí)刻只能有一個(gè)事務(wù)對(duì)數(shù)據(jù)進(jìn)行寫操作,InnoDB 通過鎖機(jī)制來保證這一點(diǎn)。

鎖機(jī)制的基本原理可以概括為:

  • 事務(wù)在修改數(shù)據(jù)之前,需要先獲得相應(yīng)的鎖。
  • 獲得鎖之后,事務(wù)便可以修改數(shù)據(jù)。
  • 該事務(wù)操作期間,這部分?jǐn)?shù)據(jù)是鎖定的,其他事務(wù)如果需要修改數(shù)據(jù),需要等待當(dāng)前事務(wù)提交或回滾后釋放鎖。

行鎖與表鎖:按照粒度,鎖可以分為表鎖、行鎖以及其他位于二者之間的鎖。

表鎖在操作數(shù)據(jù)時(shí)會(huì)鎖定整張表,并發(fā)性能較差;行鎖則只鎖定需要操作的數(shù)據(jù),并發(fā)性能好。

但是由于加鎖本身需要消耗資源(獲得鎖、檢查鎖、釋放鎖等都需要消耗資源),因此在鎖定數(shù)據(jù)較多情況下使用表鎖可以節(jié)省大量資源。

MySQL 中不同的存儲(chǔ)引擎支持的鎖是不一樣的,例如 MyIsam 只支持表鎖,而 InnoDB 同時(shí)支持表鎖和行鎖,且出于性能考慮,絕大多數(shù)情況下使用的都是行鎖。

如何查看鎖信息?有多種方法可以查看 InnoDB 中鎖的情況,例如:

  1. select * from information_schema.innodb_locks; #鎖的概況 
  2. show engine innodb status; #InnoDB整體狀態(tài),其中包括鎖的情況 

下面來看一個(gè)例子:

  1. #在事務(wù)A中執(zhí)行: 
  2. start transaction
  3. update account SET balance = 1000 where id = 1; 
  4. 在事務(wù)B中執(zhí)行: 
  5. start transaction
  6. update account SET balance = 2000 where id = 1; 

此時(shí)查看鎖的情況:

 

show engine innodb status 查看鎖相關(guān)的部分:

 

通過上述命令可以查看事務(wù) 24052 和 24053 占用鎖的情況;其中 lock_type 為 RECORD,代表鎖為行鎖(記錄鎖);lock_mode 為 X,代表排它鎖(寫鎖)。

除了排它鎖(寫鎖)之外,MySQL 中還有共享鎖(讀鎖)的概念。由于本文重點(diǎn)是 MySQL 事務(wù)的實(shí)現(xiàn)原理,因此對(duì)鎖的介紹到此為止。

介紹完寫操作之間的相互影響,下面討論寫操作對(duì)讀操作的影響。

臟讀、不可重復(fù)讀和幻讀

首先來看并發(fā)情況下,讀操作可能存在的三類問題。

①臟讀:當(dāng)前事務(wù)(A)中可以讀到其他事務(wù)(B)未提交的數(shù)據(jù)(臟數(shù)據(jù)),這種現(xiàn)象是臟讀。

舉例如下(以賬戶余額表為例):

 

②不可重復(fù)讀:在事務(wù) A 中先后兩次讀取同一個(gè)數(shù)據(jù),兩次讀取的結(jié)果不一樣,這種現(xiàn)象稱為不可重復(fù)讀。

臟讀與不可重復(fù)讀的區(qū)別在于:前者讀到的是其他事務(wù)未提交的數(shù)據(jù),后者讀到的是其他事務(wù)已提交的數(shù)據(jù)。

舉例如下:

 

③幻讀:在事務(wù) A 中按照某個(gè)條件先后兩次查詢數(shù)據(jù)庫,兩次查詢結(jié)果的條數(shù)不同,這種現(xiàn)象稱為幻讀。

不可重復(fù)讀與幻讀的區(qū)別可以通俗的理解為:前者是數(shù)據(jù)變了,后者是數(shù)據(jù)的行數(shù)變了。

舉例如下:

 

事務(wù)隔離級(jí)別

sql 標(biāo)準(zhǔn)中定義了四種隔離級(jí)別,并規(guī)定了每種隔離級(jí)別下上述幾個(gè)問題是否存在。

一般來說,隔離級(jí)別越低,系統(tǒng)開銷越低,可支持的并發(fā)越高,但隔離性也越差。

隔離級(jí)別與讀問題的關(guān)系如下:

 

在實(shí)際應(yīng)用中,讀未提交在并發(fā)時(shí)會(huì)導(dǎo)致很多問題,而性能相對(duì)于其他隔離級(jí)別提高卻很有限,因此使用較少。

可串行化強(qiáng)制事務(wù)串行,并發(fā)效率很低,只有當(dāng)對(duì)數(shù)據(jù)一致性要求極高且可以接受沒有并發(fā)時(shí)使用,因此使用也較少。

因此在大多數(shù)數(shù)據(jù)庫系統(tǒng)中,默認(rèn)的隔離級(jí)別是讀已提交(如 Oracle)或可重復(fù)讀(后文簡(jiǎn)稱 RR)。

可以通過如下兩個(gè)命令分別查看全局隔離級(jí)別和本次會(huì)話的隔離級(jí)別:

 

InnoDB 默認(rèn)的隔離級(jí)別是 RR,后文會(huì)重點(diǎn)介紹 RR。需要注意的是,在 SQL 標(biāo)準(zhǔn)中,RR 是無法避免幻讀問題的,但是 InnoDB 實(shí)現(xiàn)的 RR 避免了幻讀問題。

MVCC

RR 解決臟讀、不可重復(fù)讀、幻讀等問題,使用的是 MVCC:MVCC 全稱 Multi-Version Concurrency Control,即多版本的并發(fā)控制協(xié)議。

下面的例子很好的體現(xiàn)了 MVCC 的特點(diǎn):在同一時(shí)刻,不同的事務(wù)讀取到的數(shù)據(jù)可能是不同的(即多版本)——在 T5 時(shí)刻,事務(wù) A 和事務(wù) C 可以讀取到不同版本的數(shù)據(jù)。

 

MVCC 最大的優(yōu)點(diǎn)是讀不加鎖,因此讀寫不沖突,并發(fā)性能好。InnoDB 實(shí)現(xiàn) MVCC,多個(gè)版本的數(shù)據(jù)可以共存,主要是依靠數(shù)據(jù)的隱藏列(也可以稱之為標(biāo)記位)和 undo log。

其中數(shù)據(jù)的隱藏列包括了該行數(shù)據(jù)的版本號(hào)、刪除時(shí)間、指向 undo log 的指針等等。

當(dāng)讀取數(shù)據(jù)時(shí),MySQL 可以通過隱藏列判斷是否需要回滾并找到回滾需要的 undo log,從而實(shí)現(xiàn) MVCC;隱藏列的詳細(xì)格式不再展開。

下面結(jié)合前文提到的幾個(gè)問題分別說明。

①臟讀

 

當(dāng)事務(wù) A 在 T3 時(shí)間節(jié)點(diǎn)讀取 zhangsan 的余額時(shí),會(huì)發(fā)現(xiàn)數(shù)據(jù)已被其他事務(wù)修改,且狀態(tài)為未提交。

此時(shí)事務(wù) A 讀取最新數(shù)據(jù)后,根據(jù)數(shù)據(jù)的 undo log 執(zhí)行回滾操作,得到事務(wù) B 修改前的數(shù)據(jù),從而避免了臟讀。

②不可重復(fù)讀

 

當(dāng)事務(wù) A 在 T2 節(jié)點(diǎn)第一次讀取數(shù)據(jù)時(shí),會(huì)記錄該數(shù)據(jù)的版本號(hào)(數(shù)據(jù)的版本號(hào)是以 row 為單位記錄的),假設(shè)版本號(hào)為 1;當(dāng)事務(wù) B 提交時(shí),該行記錄的版本號(hào)增加,假設(shè)版本號(hào)為 2。

當(dāng)事務(wù) A 在 T5 再一次讀取數(shù)據(jù)時(shí),發(fā)現(xiàn)數(shù)據(jù)的版本號(hào)(2)大于第一次讀取時(shí)記錄的版本號(hào)(1),因此會(huì)根據(jù) undo log 執(zhí)行回滾操作,得到版本號(hào)為 1 時(shí)的數(shù)據(jù),從而實(shí)現(xiàn)了可重復(fù)讀。

③幻讀

InnoDB 實(shí)現(xiàn)的 RR 通過 next-keylock 機(jī)制避免了幻讀現(xiàn)象。

next-keylock 是行鎖的一種,實(shí)現(xiàn)相當(dāng)于 record lock(記錄鎖) + gap lock(間隙鎖);其特點(diǎn)是不僅會(huì)鎖住記錄本身(record lock 的功能),還會(huì)鎖定一個(gè)范圍(gap lock 的功能)。

當(dāng)然,這里我們討論的是不加鎖讀:此時(shí)的 next-key lock 并不是真的加鎖,只是為讀取的數(shù)據(jù)增加了標(biāo)記(標(biāo)記內(nèi)容包括數(shù)據(jù)的版本號(hào)等);準(zhǔn)確起見姑且稱之為類 next-key lock 機(jī)制。

還是以前面的例子來說明:

 

當(dāng)事務(wù) A 在 T2 節(jié)點(diǎn)第一次讀取 0

這樣當(dāng) T5 時(shí)刻再次讀取 0

小結(jié):概括來說,InnoDB 實(shí)現(xiàn)的 RR,通過鎖機(jī)制、數(shù)據(jù)的隱藏列、undo log 和類 next-key lock,實(shí)現(xiàn)了一定程度的隔離性,可以滿足大多數(shù)場(chǎng)景的需要。

不過需要說明的是,RR 雖然避免了幻讀問題,但是畢竟不是 Serializable,不能保證完全的隔離。

下面是一個(gè)例子,大家可以自己驗(yàn)證一下:

 

一致性

基本概念

一致性是指事務(wù)執(zhí)行結(jié)束后,數(shù)據(jù)庫的完整性約束沒有被破壞,事務(wù)執(zhí)行的前后都是合法的數(shù)據(jù)狀態(tài)。

數(shù)據(jù)庫的完整性約束包括但不限于:

  • 實(shí)體完整性(如行的主鍵存在且唯一)
  • 列完整性(如字段的類型、大小、長度要符合要求)
  • 外鍵約束
  • 用戶自定義完整性(如轉(zhuǎn)賬前后,兩個(gè)賬戶余額的和應(yīng)該不變)

實(shí)現(xiàn)

可以說,一致性是事務(wù)追求的最終目標(biāo):前面提到的原子性、持久性和隔離性,都是為了保證數(shù)據(jù)庫狀態(tài)的一致性。此外,除了數(shù)據(jù)庫層面的保障,一致性的實(shí)現(xiàn)也需要應(yīng)用層面進(jìn)行保障。

實(shí)現(xiàn)一致性的措施包括:

  • 保證原子性、持久性和隔離性,如果這些特性無法保證,事務(wù)的一致性也無法保證。
  • 數(shù)據(jù)庫本身提供保障,例如不允許向整形列插入字符串值、字符串長度不能超過列的限制等。
  • 應(yīng)用層面進(jìn)行保障,例如如果轉(zhuǎn)賬操作只扣除轉(zhuǎn)賬者的余額,而沒有增加接收者的余額,無論數(shù)據(jù)庫實(shí)現(xiàn)的多么完美,也無法保證狀態(tài)的一致。

總結(jié)

下面總結(jié)一下 ACID 特性及其實(shí)現(xiàn)原理:

  • 原子性:語句要么全執(zhí)行,要么全不執(zhí)行,是事務(wù)最核心的特性。事務(wù)本身就是以原子性來定義的;實(shí)現(xiàn)主要基于 undo log。
  • 持久性:保證事務(wù)提交后不會(huì)因?yàn)殄礄C(jī)等原因?qū)е聰?shù)據(jù)丟失;實(shí)現(xiàn)主要基于 redo log。
  • 隔離性:保證事務(wù)執(zhí)行盡可能不受其他事務(wù)影響;InnoDB 默認(rèn)的隔離級(jí)別是 RR,RR 的實(shí)現(xiàn)主要基于鎖機(jī)制、數(shù)據(jù)的隱藏列、undo log 和類 next-key lock 機(jī)制。
  • 一致性:事務(wù)追求的最終目標(biāo),一致性的實(shí)現(xiàn)既需要數(shù)據(jù)庫層面的保障,也需要應(yīng)用層面的保障。

參考文獻(xiàn):

  • 《MySQL 技術(shù)內(nèi)幕:InnoDB 存儲(chǔ)引擎》
  • 《高性能 MySQL》
  • 《MySQL 運(yùn)維內(nèi)參》
  • https://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_acid
  • https://dev.mysql.com/doc/refman/5.6/en/innodb-next-key-locking.html
  • http://blog.sina.com.cn/s/blog_499740cb0100ugs7.html
  • https://mp.weixin.qq.com/s/2dwGBTmu_da2x-HiHlN0vw
  • http://www.cnblogs.com/chenpingzhao/p/5065316.html
  • https://juejin.im/entry/5ba0a254e51d450e735e4a1f
  • http://hedengcheng.com/?p=771

【51CTO原創(chuàng)稿件,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文作者和出處為51CTO.com】

 

責(zé)任編輯:武曉燕 來源: 51CTO技術(shù)棧
相關(guān)推薦

2018-05-22 10:09:09

數(shù)據(jù)庫MySQL優(yōu)化原理

2019-04-03 09:27:01

MySQLInnoDB務(wù)ACID

2021-07-31 23:14:26

OpenCL框架語言

2021-01-27 08:12:04

Dotnet函數(shù)數(shù)據(jù)

2021-09-15 06:55:34

異步LinqC#

2021-12-15 09:32:41

Linux系統(tǒng)負(fù)載

2024-12-30 13:58:14

2021-10-19 10:10:51

MySQL事務(wù)隔離級(jí)別數(shù)據(jù)庫

2021-07-08 07:08:21

MySQL ACID 數(shù)據(jù)庫

2020-03-18 13:40:03

Spring事數(shù)據(jù)庫代碼

2021-04-14 07:47:59

AttributeC#屬性

2022-04-28 10:41:08

SaaS業(yè)務(wù)方式

2020-02-13 10:14:11

MySQL事務(wù)ACID

2023-12-22 13:46:41

數(shù)據(jù)訓(xùn)練

2010-09-08 15:55:20

SQL事務(wù)特性

2023-12-26 08:08:02

Spring事務(wù)MySQL

2024-03-13 08:34:22

2023-02-24 15:24:14

MySQL數(shù)據(jù)庫管理分庫分表

2017-07-06 17:03:45

BP算法Python神經(jīng)網(wǎng)絡(luò)

2024-10-10 09:12:10

Spring接口初始化
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)