MYSQL事务特点
文章目錄
- 事務的定義:
- 事務的特征(ACID):
- 事務的原子性(Atomic)
- 事務的一致性(Consistency)
- 事務的隔離性(Isolation)
- 事務的持久性(Durability)
- 事務的使用
- 1、查看事務:select @@autocommit
- 2、事務設置:set autocommit
- 3、事務操作
- 3.1、開啟事務:begin或start transaction
- 3.2 事務提交:commit
- 3.3、事務回滾:rollback
- 3.4、保存點:savepoint point1
- 4、查看隔離級別:select @@transaction_isolation;
- 并發事務問題
- 1、臟讀(Dirty read)
- 2、不可重復讀(Unrepeatableread)
- 3、幻讀(Phantom read)
- 事務隔離級別
- 1、READ-UNCOMMITTED(讀取未提交)
- 2、READ-COMMITTED(讀取已提交)
- 3、REPEATABLE-READ(可重復讀)
- 4、SERIALIZABLE(可串行化)
- 事務原理
- 1、MVCC多版本控制
- MVCC實現原理
- MVCC特點:
- 2、事務日志
- 2.1、redo log
- 2.2、undo lo
- 2.3、binlog
- 主從復制原理
事務的定義:
一個事務是由一條或者多條對數據庫操作的SQL語句所組成的一個不可分割的單元,只有當事務中的所有操作都正常執行完了,整個事務才會被提交給數據庫;如果有部分事務處理失敗,那么事務就要回退到最初的狀態,因此,事務要么全部執行成功,要么全部失敗。
事務的特征(ACID):
事務的原子性(Atomic)
事務是一個不可分割的單元,事務必須具有原子性,即要么全部執行,要么全部不執行,不允許部分執行
事務的一致性(Consistency)
一個事務執行之前和執行之后,數據庫中的數據必須保持一致性狀態
事務的隔離性(Isolation)
當兩個或者多個事務并發執行時,未來保證數據的安全性,當一個事務內操作和其他事務的操作需要起到隔離起來,不被其他正在執行的事務所看到,隔離性使得每個事務的更新在提交之前,對于其他事務是不可見的
事務的持久性(Durability)
事務完成之后,數據庫需要保證當前事務的修改時永久性的,即使數據庫因為故障出錯,也應該恢復數據
事務的使用
1、查看事務:select @@autocommit
通過select @@autocommit;;可以查看事務狀態
默認為1:表示事務是自動提交 0表示手動提交
2、事務設置:set autocommit
使用set autocommit=0; 進行事務手動提交
set autocommit =0; Query OK, 0 rows affected (0.01 sec)3、事務操作
3.1、開啟事務:begin或start transaction
mysql> begin; Query OK, 0 rows affected (0.00 sec)mysql> start transaction; Query OK, 0 rows affected (0.00 sec)3.2 事務提交:commit
當一個或者多個SQL組成的事務需要提交時,就通過commit來操作
3.3、事務回滾:rollback
如果執行的過程中有部分事務執行失敗,回滾到事務最初的狀態
3.4、保存點:savepoint point1
savepoint point1;設置一個名稱為point1的保存點
rollback to point1;事務回滾到指定的point1點,而不是最初的保存點
我們可以看到1009 瑞文沒有添加成功 因為我們回滾到了添加瑞文之前了所以沒有添加成功。
4、查看隔離級別:select @@transaction_isolation;
select @@tx_isolation;(久版本)
select @@transaction_isolation;(新版本)
并發事務問題
在典型的應用程序中,多個事務并發運行,經常會操作相同的數據來完成各自的任務(多個用戶對統一數據進行操作)。并發雖然是必須的,但可能會導致以下的問題:
1、臟讀(Dirty read)
A事務讀取了B事務尚未提交的更改數據,并在這個讀取的臟數據上進行操作。如果這時B事務恰巧進行了回滾事務,那么A事務讀取的事務是不被承認的
2、不可重復讀(Unrepeatableread)
在同一個事務中,同一個讀操作對同一個數據的前后兩次讀取產生了不同的結果,這就是不可重復讀。
3、幻讀(Phantom read)
幻像讀是指在同一個事務中以前沒有的行,由于其他事務的提交而出現的新行。
不可重復度和幻讀區別:
不可重復讀一般針對的是行級別的數據的更改(修改),不可重復讀的重點是修改 幻象讀一般針對表級別的新增數據,在統計事務中,兩次讀取的數據統計不一致,幻讀的重點在于新增或者刪除。事務隔離級別
1、READ-UNCOMMITTED(讀取未提交)
最低的隔離級別,允許讀取尚未提交的數據變更,可能會導致臟讀、幻讀或不可重復讀。
2、READ-COMMITTED(讀取已提交)
允許讀取并發事務已經提交的數據,可以阻止臟讀,但是幻讀或不可重復讀仍有可能發生。
3、REPEATABLE-READ(可重復讀)
對同一字段的多次讀取結果都是一致的,除非數據是被本身事務自己所修改,可以阻止臟讀和不可重復讀,但幻讀仍有可能發生。
4、SERIALIZABLE(可串行化)
最高的隔離級別,完全服從ACID的隔離級別。所有的事務依次逐個執行,這樣事務之間就完全不可能產生干擾,也就是說,該級別可以防止臟讀、不可重復讀以及幻讀。
MySQL InnoDB 存儲引擎的默認支持的隔離級別是 REPEATABLE-READ(可重讀)。我們可以通過SELECT @@tx_isolation;命令來查看
因為隔離級別越低,事務請求的鎖越少
事務原理
1、MVCC多版本控制
MVCC (Multiversion Concurrency Control),即多版本并發控制技術
讀鎖:也叫共享鎖、S鎖,若事務T對數據對象A加上S鎖,則事務T可以讀A但不能修改A,其他事務只能再對A加S鎖,而不能加X鎖,直到T釋放A上的S 鎖。這保證了其他事務可以讀A,但在T釋放A上的S鎖之前不能對A做任何修改。
寫鎖:又稱排他鎖、X鎖。若事務T對數據對象A加上X鎖,事務T可以讀A也可以修改A,其他事務不能再對A加任何鎖,直到T釋放A上的鎖。這保證了其他事務在T釋放A上的鎖之前不能再讀取和修改A。
表鎖:操作對象是數據表。Mysql大多數鎖策略都支持(常見mysql innodb),是系統開銷最低但并發性最低的一個鎖策略。事務t對整個表加讀鎖,則其他事務可讀不可寫,若加寫鎖,則其他事務增刪改都不行。
行級鎖:操作對象是數據表中的一行。是MVCC技術用的比較多的,但在MYISAM用不了,行級鎖用mysql的儲存引擎實現而不是mysql服務器。但行級鎖對系統開銷較大,處理高并發較好。
MVCC實現原理
1.對于數據表的每條記錄其實是這樣的:
1.DATA_TRX_ID:標記了最新更新這條行記錄的transaction id,每處理一個事務,其值自動+1,大小為6字節;
2.DATA_ROLL_PTR:指向當前記錄項的undo log記錄,找之前版本的數據就是通過這個指針;
3.DB_ROW_ID:行標識(隱藏自增ID)當由innodb自動產生聚集索引時,聚集索引包括這個DB_ROW_ID的值,否則聚集索引中不包括這個值.,這個用于索引當中,大小為6字節;
2.當我針對一條記錄執行update操作,則會
針對表某個記錄加入排他鎖
把該記錄原本的最新記錄拷貝到undo log日志中,DB_TRX_ID和DB_ROLL_PTR不變
通過修改生成新的記錄,并包含新的DB_TRX_ID和DB_ROLL_PTR
通過往復操作也就會針對此記錄形成一個版本鏈 如下圖:
begin->用排他鎖鎖定該行->記錄redo log->記錄undo log->修改當前行的值,寫事務編號,回滾指針指向undo log中的修改前的行
鏈的最頂端保存了最新的一條數據,之后通過指針指向undolog日志;
MVCC特點:
每行數據都存在一個版本,每次數據更新時都更新該版本
修改時Copy出當前版本隨意修改,各個事務之間無干擾
保存時比較版本號,如果成功(commit),則覆蓋原記錄;失敗則放棄copy(rollback)
就是每行都有版本號,保存時根據版本號決定是否成功,聽起來含有樂觀鎖的味道,而Innodb的實現方式是:
事務以排他鎖的形式修改原始數據
把修改前的數據存放于undo log,通過回滾指針與主數據關聯
修改成功(commit)啥都不做,失敗則恢復undo log中的數據(rollback)
2、事務日志
在MVCC中,要保證事務的執行用到了undolog,事務要保證ACID的完整性必須依靠事務日志做跟蹤,每一個操作在真正寫入數據數據庫之前,先寫入到日志文件中如要刪除一行數據會先在日志文件中將此行標記為刪除,但是數據庫中的數據文件并沒有發生變化。在事務引擎上的每一次寫操作都需要執行兩遍如下過程:
1、先寫入日志文件中 寫入日志文件中的僅僅是操作過程,而不是操作數據本身,所以速度比寫數據庫文件速度要快很多。
2、然后再寫入數據庫文件中 寫入數據庫文件的操作是重做事務日志中已提交的事務操作的記錄。
2.1、redo log
在innoDB的存儲引擎中,事務日志通過重做(redo)日志和innoDB存儲引擎的日志緩沖(InnoDB Log Buffer)實現。事務開啟時,事務中的操作,都會先寫入存儲引擎的日志緩沖中,在事務提交之前,這些緩沖的日志都需要提前刷新到磁盤上持久化,這就是DBA們口中常說的“日志先行”(Write-Ahead Logging)。
InnoDB 的 redo log 是固定大小的,比如可以配置為一組 4 個文件,每個文件的大小是 1GB,那么這塊日志總共就可以記錄 4GB 的操作。
2.2、undo lo
undo log主要為事務的回滾服務。在事務執行的過程中,除了記錄redo log,還會記錄一定量的undo log。undo log記錄了數據在每個操作前的狀態,如果事務執行過程中需要回滾,就可以根據undo log進行回滾操作。單個事務的回滾,只會回滾當前事務做的操作,并不會影響到其他的事務做的操作。
redo log其實保證的是事務的持久性和一致性,而undo log則保證了事務的原子性。
undo log是邏輯日志,可以理解為:
當delete一條記錄時,undo log中會記錄一條對應的insert記錄
當insert一條記錄時,undo log中會記錄一條對應的delete記錄
當update一條記錄時,它記錄一條對應相反的update記錄
2.3、binlog
關于mysql主從同步很重要,隨著系統應用訪問量逐漸增大,高并發下通常會采用mysql集群,主庫和從庫之間的數據是如何同步,其實就是通過binlog主從同步binlog來實現的。
? Binlog是server層的日志,主要做mysql功能層面的事情
? 與redo日志的區別:
主從復制原理
mysql主從復制需要三個線程,master(binlog dump thread)、slave(I/O thread 、SQL thread)。master
(1)binlog dump線程:當主庫中有數據更新時,主庫就會根據設置的binlog格式,將更新的事件類型寫入到主庫的binlog文件中,此時主庫會創建log dump線程通知slave有數據更新,當I/O線程請求日志內容時,會將此時的binlog名稱和當前更新的位置同時傳給slave的I/O線程。
slave
(2)I/O線程:該線程會連接到master,向log dump線程請求一份指定binlog文件位置的副本,并將請求回來的binlog存到本地的relay log中,relay log和binlog日志一樣也是記錄了數據更新的事件,它也是按照遞增后綴名的方式,產生多個relay log(host_name-relay-bin.000001)文件,slave會使用一個index文件( host_name-relay-bin.index)來追蹤當前正在使用的relay log文件。
(3)SQL線程:該線程檢測到relay log有更新后,會讀取并在本地做redo操作,將發生在主庫的事件在本地重新執行一遍,來保證主從數據同步。此外,如果一個relay log文件中的全部事件都執行完畢,那么SQL線程會自動將該relay log 文件刪除掉。
下面是整個復制過程的原理圖:
總結
- 上一篇: ConcurrentHashMap介绍
- 下一篇: 基础网络总结