# 事務
事務語句:
```
start transaction
select ...
update ...
update ...
commit;
```
## 事務特點
ACID
1. 原子性 Atomicity
2. 一致性 Consistency
3. 隔離性 Isolation
4. 持久性 Durability
**原子性**
一個事務必須被視為一個不可分割的最小工作單元,事務當中的操作要么全部提交成功,要么全都不能提交成功。這里的原子性更多的指的是對數據庫的修改操作(DML語言)。
實現原理:undo log,可以將沒有commit的新值恢復到舊值。
**持久性**
一旦事務提交了,其操作所做的修改會永久的保存到數據庫中。
實現原理:redo log。
**隔離性**
一般來說,一個事務所做的修改在最終提交之前,對于其他事務是不可見,但是這是根據不同的隔離級別而確定的,對于不同的隔離級別可能會有不同的影響。隔離性用在并發的場景才起作用。
### 隔離級別
:-: 
1. READ UNCOMMITTED 讀取未提交
在該隔離級別中,一個事務中可以看到另外一個事務未commit的修改內容。發生這種情況就叫做`臟讀:`即事務可以讀取到其他事務未提交的操作。
~~~
?tips:所以這種級別一般很少使用
~~~
2. READ COMMITTED 提交讀
可以讀取別的事務已經提交的內容,滿足事務隔離性的定義,但是有可能會出現不可重復讀。
`不可重復讀:`在同個事務中兩次讀取數據庫的內容前后不一致。
3. REPEAABLE READ 可重復讀
該級別解決了臟讀的問題,同時解決了在同個事務中兩次讀取數據庫的內容不一致的不可重復讀的問題。但是可能會出現幻讀(phantom Read)的問題。
`幻讀:`當某個事務在讀取某個范圍的記錄時,另外一個事務又在該范圍內插入了新的記錄,當之前的事務再次讀取該范圍的記錄時,就會產生幻讀。
`該隔離級別是MYSQL中默認的級別。一般都會設置成RR。`
4. SERIALIZABLE 可串行化
Serializables是數據庫最高的隔離級別,使用該級別可以強制事務串行執行。強制事務串行執行了之后也就不會出現臟讀、不可重復讀、幻讀問題了。
設置不同隔離級別:
```
set session transaction isolation level read committed; # 設置為讀已提交隔離級別。 當前會話生效
```
**一致性**
數據庫總是從一個一致性的狀態轉化到另外一個一致性的狀態。AID最終是為了保證一致性。
## 多版本并發控制MVCC
Multi Version Concurrency Control,屬于一種樂觀鎖,不用在讀寫沖突的時候加上鎖,屬于一種`快照讀`的方式,提高并發性。而在每次讀寫沖突都加鎖是屬于一種悲觀鎖,屬于`當前讀`的方式。InnoDB采取樂觀鎖、快照讀的方式來提供并發性。
- 當前讀:讀取當前最新的版本號。
- 快照讀:讀取歷史的版本號,這樣即是在同一行進行讀寫操作也沒有關系。
MVCC的實現方式:
通過在每行記錄后面保存兩個隱藏的列,一個列保存了行的創建版本號,一個列保存了行的刪除版本號。每次開啟一個新的事務,系統版本號就會自動遞增。同時會將該系統版本號作為事務的版本號。讀操作時只會讀取該事務開始前的數據庫快照數據。
讀寫沖突種類,MVCC就是用來解決讀寫沖突問題,提供并發性。
- 讀寫
- 寫寫
**MVCC的實現原理:**
1. 版本鏈
2. undo log
3. Read view
### 版本鏈
數據庫的每行數據中都會有隱藏的幾個字段,分別是`db_trx_id`、`db_roll_pointer`、`db_row_id`。
- db_trx_id:6byte,最近修改或者插入的事務id。
- db_roll_pointer:版本鏈的關鍵,7byte,**回滾指針**,指向這條記錄的上一個版本,這些版本數據存儲與一個特定的區域。**主要用于配合undo日志。**
- db_row_id:隱含自增的ID,沒有創建聚簇索引的時候會添加上。
- 是否刪除的字段,數據庫刪除的時候并不會真正的刪除,而是修改flag的標志位。
版本鏈的是實現主要通過db_roll_pointer指針和undo日志配合實現,行中的db_roll_pointer指向undo log。每次記錄更新的時候,就會將舊值放到undo log中,undo log中也有一個db_roll_pointer,用于指向上一個版本的undo log段的內容,最終形成了一條記錄了歷史版本內容的鏈。也就是快照!**同時也會在undo log中存放事務的id,可用于Read View中判斷版本的可見性。**
:-: 
圖片來源:https://www.php.cn/mysql-tutorials-460111.html
### undo log
主要用于記錄數據被修改之前的日志,在表修改之前會先把數據拷貝到undo log里,當事務進行回滾的時候可以用undo log日志的內容進行恢復。有如下的兩個主要用途
- 保證事務的原子性和一致性。
- 用于MVCC快照讀,因為在undo log中保留了歷史的版本數據。
兩種主要的undo log:
1. insert undo log
事務失敗時用于回滾,事務提交時可以直接丟棄。
2. undate undo log
事務在進行命令delete或者update時產生的undo log,在事務回滾和快照讀的時候都需要。
### Read View
讀視圖,**解決哪些數據可以被當前事務讀取的問題。**
用于解決事務可見性的問題,每當開啟一個事務的時候,就會生成一個當前數據系統的一個視圖,該視圖包含如下的幾個內容:
- trx_ids:當前系統未提交的事務。
- low_limit_id:創建read view時當前系統的**最大事務版本號+1**。
- up_limit_id:創建read view時當前系統的未提交事務的**最小版本號**。
- creator_trx_id:創建當前read view的事務版本號。
可見性的判斷:
1. db_trx_id < up_limit_id
在當前事務創建前數據已經存在,可讀。
2. db_trx_id == creator_trx_id
當前事務id和數據id一樣,證明數據在當前數據創建,可以讀取。
3. db_trx_id >= low_limit_id
數據在當前read view創建之后創建,不可讀取。
4. db_trx_id是否在trx_ids中?
- 在:不可讀。
- 不在,可以顯示。
### MVCC在RR和RC兩種隔離級別所起的作用
對于RR隔離級別,在第一個讀的時候會創建一個Read View,此后每次讀用的都是同一個Read View,如果有其他的事務id在該Read View的trx_ids中,則其對行的數據的修改對當前事務是不可見,也就實現了可重復讀。
對于RC隔離級別,在每次讀取的時候都會創建一個Read View,這樣有可能讀取到其他事務的內容。
總之:MVCC就是在使用RR、RC隔離級別下,調用select語句的時候可以查詢歷史版本數據的內容,從而避免了在高并發場景下的大量讀寫沖突問題。其中undo log用于解決歷史版本數據保存在哪的問題,read view用于解決哪些歷史版本的數據應該被當前事務讀取到的問題,版本鏈則用于串聯所有的歷史版本數據,方便找到所需要的歷史版本數據。
- 第一章 Java基礎
- ThreadLocal
- Java異常體系
- Java集合框架
- List接口及其實現類
- Queue接口及其實現類
- Set接口及其實現類
- Map接口及其實現類
- JDK1.8新特性
- Lambda表達式
- 常用函數式接口
- stream流
- 面試
- 第二章 Java虛擬機
- 第一節、運行時數據區
- 第二節、垃圾回收
- 第三節、類加載機制
- 第四節、類文件與字節碼指令
- 第五節、語法糖
- 第六節、運行期優化
- 面試常見問題
- 第三章 并發編程
- 第一節、Java中的線程
- 第二節、Java中的鎖
- 第三節、線程池
- 第四節、并發工具類
- AQS
- 第四章 網絡編程
- WebSocket協議
- Netty
- Netty入門
- Netty-自定義協議
- 面試題
- IO
- 網絡IO模型
- 第五章 操作系統
- IO
- 文件系統的相關概念
- Java幾種文件讀寫方式性能對比
- Socket
- 內存管理
- 進程、線程、協程
- IO模型的演化過程
- 第六章 計算機網絡
- 第七章 消息隊列
- RabbitMQ
- 第八章 開發框架
- Spring
- Spring事務
- Spring MVC
- Spring Boot
- Mybatis
- Mybatis-Plus
- Shiro
- 第九章 數據庫
- Mysql
- Mysql中的索引
- Mysql中的鎖
- 面試常見問題
- Mysql中的日志
- InnoDB存儲引擎
- 事務
- Redis
- redis的數據類型
- redis數據結構
- Redis主從復制
- 哨兵模式
- 面試題
- Spring Boot整合Lettuce+Redisson實現布隆過濾器
- 集群
- Redis網絡IO模型
- 第十章 設計模式
- 設計模式-七大原則
- 設計模式-單例模式
- 設計模式-備忘錄模式
- 設計模式-原型模式
- 設計模式-責任鏈模式
- 設計模式-過濾模式
- 設計模式-觀察者模式
- 設計模式-工廠方法模式
- 設計模式-抽象工廠模式
- 設計模式-代理模式
- 第十一章 后端開發常用工具、庫
- Docker
- Docker安裝Mysql
- 第十二章 中間件
- ZooKeeper