您好,登錄后才能下訂單哦!
這篇文章主要為大家分享數據庫事務的四大特性,特性包括:原子性、隔離性、永久性、一致性,接下來為大家介紹這四大特性的定義和在 InnoDB 引擎中的實現。
一次操作是不可分割的,要么全部成功,要么全部失敗。比如我們的轉賬操作,不允許出款方成功,收款方失敗這種情況,要么都成功,要么多失敗,不可能出現中間狀態。
InnoDB 引擎使用 undo log(歸滾日志)來保證原子性操作,你對數據庫的每一條數據的改動(INSERT、DELETE、UPDATE)都會被記錄到 undo log 中,比如以下這些操作:
當事務執行失敗或者調用了 rollback 方法時,就會觸發回滾事件,利用 undo log 中記錄將數據回滾到修改之前的樣子。
更多關于 undo log 的信息,后面再單獨開一篇文章打卡。
多個事務并發執行的時候,事務內部的操作與其他事務是隔離的,并發執行的各個事務之間不能互相干擾。
隔離性可能會引入臟讀(dirty read)、不可重復讀(non-repeatable read)、幻讀(phantom read)等問題,為了解決這些問題就引入了“隔離級別”的概念。
SQL 標準的事務隔離級別包括:讀未提交(read uncommitted)、讀提交(read committed)、可重復讀(repeatable read)和串行化(serializable):
SQL標準中規定,針對不同的隔離級別,并發事務可以發生不同嚴重程度的問題,具體情況如下:
隔離級別 | 臟讀 | 不可重復讀 | 幻讀 |
---|---|---|---|
讀未提交 | 可能 | 可能 | 可能 |
讀提交 | 不可能 | 可能 | 可能 |
可重復讀 | 不可能 | 不可能 | 可能 |
串行化 | 不可能 | 不可能 | 不可能 |
上面就是幾種隔離級別可能出現的并發問題,但是有必要說一下,你隔離得越嚴實,效率就會越低。
InnoDB 引擎是如何保證隔離性的?利用鎖和 MVCC 機制。這里簡單的介紹一下 MVCC 機制,也叫多版本并發控制,在使用 READ COMMITTD、REPEATABLE READ 這兩種隔離級別的事務下,每條記錄在更新的時候都會同時記錄一條回滾操作,就會形成一個版本鏈,在執行普通的 SELECT 操作時訪問記錄的版本鏈的過程,這樣子可以使不同事務的讀-寫、寫-讀操作并發執行,從而提升系統性能。
事務一旦提交,它對數據庫的改變就應該是永久性的。接下來的其他操作或故障不應該對其有任何影響。
要保證持久性很簡單,就是每次事務提交的時候,都將數據刷磁盤上,這樣一定保證了安全性,但是要知道如果每次事務提交都將數據寫入到磁盤的話,頻繁的 IO 操作,成本太高,數據庫的性能極低,所以這種方式不可取。
InnoDB 引擎是怎么解決的?InnoDB 引擎引入了一個中間層來解決這個持久性的問題,我們把這個叫做 redo log(歸檔日志)。
為什么要引入 redo log?redo log 可以保證持久化又可以保證數據庫的性能,相比于直接刷盤,redo log 有以下兩個優勢:
InnoDB 引擎是怎么做的?當有一條記錄需要更新的時候,InnoDB 引擎就會先把記錄寫到 redo log 里面,并更新內存,這個時候更新就算完成了。當數據庫宕機重啟的時候,會將 redo log 中的內容恢復到數據庫中,再根據 undo log和 binlog 內容決定回滾數據還是提交數據。
更多 redo log,后面我打算單獨寫一篇文章。
一致性簡單一點說就是數據執行前后都要處于一種合法的狀態,比如身份證號不能重復,性別只能是男或者女,高考的分數只能在0~750之間,紅綠燈只有3種顏色,房價不能為負的等等, 只有符合這些約束的數據才是有效的,比如有個小孩兒跟你說他高考考了1000分,你一聽就知道他胡扯呢。數據庫世界只是現實世界的一個映射,現實世界中存在的約束當然也要在數據庫世界中有所體現。如果數據庫中的數據全部符合現實世界中的約束(all defined rules),我們說這些數據就是一致的,或者說符合一致性的。
要保證數據庫的數據一致性,要在以下兩個方面做努力:
NOT NULL
來拒絕NULL
值得插入等。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。