[TOC]
## 事務
### 什么是事務?
事務是邏輯上的一組操作,要么都執行,要么都不執行
### 事務的四大特性
原子性(Atomicity)、一致性(Consistent)、隔離性(Isalotion)、持久性(Durable)**,簡稱為`ACID`
1. **原子性**:是指事務的原子性操作,**對數據的修改要么全部執行成功,要么全部失敗,實現事務的原子性,undo log保證**
2. **一致性**:是指**執行事務前后的狀態要一致**,可以理解為數據一致性。**undo log+redo log保證**
3. **隔離性**:側重指**事務之間相互隔離,不受影響**,這個與事務設置的隔離級別有密切的關系。**鎖(共享、排他)+mvcc保證**
4. **持久性**:則是指在**一個事務提交后,這個事務的狀態會被持久化到數據庫中,也就是事務提交,對數據的新增、更新將會持久化到數據庫中。redo log保證**
Mysql默認的隔離級別:**可重復讀**。
REPEATABLE-READ(可重讀)**事務隔離級別下使用的是Next-Key Lock 鎖算法,因此可以避免幻讀的產生,這與其他數據庫系統(如 SQL Server)是不同的。所以說InnoDB 存儲引擎的默認支持的隔離級別是**REPEATABLE-READ(可重讀)**已經可以完全保證事務的隔離性要求,即達到了 SQL標準的**SERIALIZABLE(可串行化)
### 并發事務處理帶來的問題
* 更新丟失(Lost Update):事務A和事務B選擇同一行,然后基于最初選定的值更新該行時,由于兩個事務都不知道彼此的存在,就會發生丟失更新問題
* 臟讀(Dirty Reads):事務A讀取了事務B更新的數據,然后B回滾操作,那么A讀取到的數據是臟數據
* 不可重復讀(Non-Repeatable Reads):事務 A 多次讀取同一數據,事務B在事務A多次讀取的過程中,對數據作了更新并提交,導致事務A多次讀取同一數據時,結果不一致。
* 幻讀(Phantom Reads):幻讀與不可重復讀類似。它發生在一個事務A讀取了幾行數據,接著另一個并發事務B插入了一些數據時。在隨后的查詢中,事務A就會發現多了一些原本不存在的記錄,就好像發生了幻覺一樣,所以稱為幻讀。
### 并發事務處理帶來的問題的解決辦法
* “更新丟失”通常是應該完全避免的。但防止更新丟失,并不能單靠數據庫事務控制器來解決,需要應用程序對要更新的數據加必要的鎖來解決,因此,防止更新丟失應該是應用的責任。
* “臟讀” 、 “不可重復讀”和“幻讀” ,其實都是數據庫讀一致性問題,必須由數據庫提供一定的事務隔離機制來解決:
* 一種是加鎖:在讀取數據前,對其加鎖,阻止其他事務對數據進行修改。
* 另一種是數據多版本并發控制(`MultiVersion Concurrency Control`,簡稱`MVCC`或`MCC`),也稱為多版本數據庫:不用加任何鎖, 通過一定機制生成一個數據請求時間點的一致性數據快照 (`Snapshot`),并用這個快照來提供一定級別 (語句級或事務級) 的一致性讀取。從用戶的角度來看,好象是數據庫可以提供同一數據的多個版本。
### 隔離級別
**讀未提交-讀提交-可重復讀-串行化**,**級別越來越高,隔離也就越來越嚴實,到最后的串行化,當出現讀寫鎖沖突的時候,后面的事務只能等前面的事務完成后才能繼續訪問**
1. **讀未提交:一個事務還沒提交時,它做的變更就能被其他事務看到,從而產生了臟讀**。
2. **讀提交:一個事務提交之后,它做的變更才能被其他事務看到,從而產生不可重復讀。**
3. **可重復讀:一個事務執行過程中看到的數據,一直跟這個事務啟動時看到的數據是一致的,(產生幻讀,在Mysql的中通過MVCC多版本控制的一致性視圖解決了不可重復讀問題以及通過間隙鎖解決了幻讀問題。)**
4. **串行化:對于同一行記錄,若是讀寫鎖發生沖突,后面訪問的事務只能等前面的事務執行完才能繼續訪問**。
* 臟讀:讀到其他事務未提交的數據;
* 不可重復讀:前后讀取的數據不一致;
* 幻讀:前后讀取的記錄數量不一致。
**幻讀和不可重復讀的區別:**
>不可重復讀的重點是修改,幻讀的重點在于新增或者刪除
**不可重復讀的重點是修改**:在同一事務中,同樣的條件,第一次讀的數據和第二次讀的數據不一樣。(因為中間有其他事務提交了修改)
**幻讀的重點在于新增或者刪除**:在同一事務中,同樣的條件,,第一次和第二次讀出來的記錄數不一樣。(因為中間有其他事務提交了插入/刪除)
## MVCC
### 什么是MVCC
MVCC是一種多版本并發控制機制
MVCC中規定**每一行數據都有多個不同的版本,一個事務更新操作完后就生成一個新的版本**
### MVCC是為了解決什么問題
* 大多數的MYSQL事務型存儲引擎,如,InnoDB,Falcon以及PBXT都不使用一種簡單的行鎖機制.事實上,他們都和MVCC–多版本并發控制來一起使用.
* 大家都應該知道,鎖機制可以控制并發操作,但是其系統開銷較大,而MVCC可以在大多數情況下代替行級鎖,使用MVCC,能降低其系統開銷.
### MVCC實現
MVCC是通過保存數據在某個時間點的快照來實現的,不同存儲引擎的MVCC實現是不同的,典型的有樂觀并發控制和悲觀并發控制.
### MVCC 具體實現分析(原理) ?
InnoDB的MVCC,是通過在每行記錄后面保存兩個隱藏的列來實現的,這兩個列,分別保存了這個行的創建時間,一個保存的是行的刪除時間。這里存儲的并不是實際的時間值,而是系統版本號(可以理解為事務的ID),每開始一個新的事務,系統版本號就會自動遞增,事務開始時刻的系統版本號會作為事務的ID.
### REPEATABLE READ(可重讀)隔離級別下MVCC如何工作:
* SELECT:InnoDB會根據以下兩個條件檢查每行記錄:
* InnoDB只查找版本早于當前事務版本的數據行,這樣可以確保事務讀取的行,要么是在開始事務之前已經存在要么是事務自身插入或者修改過的
* 行的刪除版本號要么未定義,要么大于當前事務版本號,這樣可以確保事務讀取到的行在事務開始之前未被刪除
* 只有符合上述兩個條件的才會被查詢出來
* INSERT:InnoDB為新插入的每一行保存當前系統版本號作為行版本號
* DELETE:InnoDB為刪除的每一行保存當前系統版本號作為行刪除標識
* UPDATE:InnoDB為插入的一行新紀錄保存當前系統版本號作為行版本號,同時保存當前系統版本號到原來的行作為刪除標識
保存這兩個額外系統版本號,使大多數操作都不用加鎖。使數據操作簡單,性能很好,并且也能保證只會讀取到符合要求的行。不足之處是每行記錄都需要額外的存儲空間,需要做更多的行檢查工作和一些額外的維護工作。
**MVCC 只在 COMMITTED READ(讀提交)和REPEATABLE READ(可重復讀)兩種隔離級別下工作**。
## 數據庫日志
### 事務日志可以幫助提高事務效率
* 使用事務日志,存儲引擎在修改表的數據時只需要修改其內存拷貝,再把該修改行為記錄到持久在硬盤上的事務日志中,而不用每次都將修改的數據本身持久到磁盤。
* 事務日志采用的是追加的方式,因此寫日志的操作是磁盤上一小塊區域內的順序I/O,而不像隨機I/O需要在磁盤的多個地方移動磁頭,所以采用事務日志的方式相對來說要快得多。
* 事務日志持久以后,內存中被修改的數據在后臺可以慢慢刷回到磁盤。
* 如果數據的修改已經記錄到事務日志并持久化,但數據本身沒有寫回到磁盤,此時系統崩潰,存儲引擎在重啟時能夠自動恢復這一部分修改的數據。
## 事務的實現
事務的實現是基于數據庫的存儲引擎。不同的存儲引擎對事務的支持程度不一樣。MySQL 中支持事務的存儲引擎有 InnoDB 和 NDB。
### 事務的實現就是如何實現ACID特性。
事務的隔離性是通過鎖實現,而事務的原子性、一致性和持久性則是通過 事務日志實現 。
### 事務是如何通過日志來實現的
事務日志包括:**重做日志redo和回滾日志undo**
* redo log(重做日志)實現了持久化 在innoDB的存儲引擎中,事務日志通過重做(redo)日志和innoDB存儲引擎的日志緩沖(InnoDB Log Buffer)實現。事務開啟時,事務中的操作,都會先寫入存儲引擎的日志緩沖中,在事務提交之前,這些緩沖的日志都需要提前刷新到磁盤上持久化,這就是DBA們口中常說的“日志先行”(Write-Ahead Logging)。
當事務提交之后,在Buffer Pool中映射的數據文件才會慢慢刷新到磁盤。此時如果數據庫崩潰或者宕機,那么當系統重啟進行恢復時,就可以根據redo log中記錄的日志,把數據庫恢復到崩潰前的一個狀態。未完成的事務,可以繼續提交,也可以選擇回滾,這基于恢復的策略而定。
在系統啟動的時候,就已經為redo log分配了一塊連續的存儲空間,以順序追加的方式記錄Redo Log,通過順序IO來改善性能。所有的事務共享redo log的存儲空間,它們的Redo Log按語句的執行順序,依次交替的記錄在一起。
* undo log(回滾日志) ?實現一致性
undo log 主要為事務的回滾服務。在事務執行的過程中,除了記錄redo log,還會記錄一定量的undo log。undo log記錄了數據在每個操作前的狀態,如果事務執行過程中需要回滾,就可以根據undo log進行回滾操作。單個事務的回滾,只會回滾當前事務做的操作,并不會影響到其他的事務做的操作。
Undo記錄的是已部分完成并且寫入硬盤的未完成的事務,默認情況下回滾日志是記錄下表空間中的(共享表空間或者獨享表空間)
二種日志均可以視為一種恢復操作,redo_log是恢復提交事務修改的頁操作,而undo_log是回滾行記錄到特定版本。二者記錄的內容也不同,redo_log是物理日志,記錄頁的物理修改操作,而undo\_log是邏輯日志,根據每行記錄進行記錄。
### mysql中的日志文件都有哪些
①重做日志 redo log
②回滾日志 undo log
③二進制日志 bin log
④錯誤日志 error log
⑤慢查詢日志 slow query log
⑥一般查詢日志 general log
⑦中繼日志 relay log
### Mysql中redolog 和 binlog的作用和區別
①redolog屬于物理日志,記錄改數據頁的更新狀態內容
②binlog屬于邏輯日志,記錄更新的操作語句的原始邏輯
③redolog是循環寫,日志的空間大小是固定的;binlog是追加寫入,寫完一個寫下一個,不會進行數據的覆蓋
### 作為主從復制和數據恢復使用哪一個?
redo log作為服務器異常宕機后事務數據自動恢復使用,binlog可以作為主從復制和數據恢復使用,binlog沒有自動crash-safe的能力
### bin log
作用:用于主從復制,實現主從同步
### redo log
作用:確保日志的持久性,防止在發生故障,臟頁未寫入磁盤。重啟數據庫會進行redo log執行重做,達到事務一致性
### undo log
作用:保證數據的原子性,記錄事務發生之前的一個版本,用于回滾,innodb事務可重復讀和讀取已提交 隔離級別就是通過mvcc+undo實現
### relay log
作用:用于數據庫主從同步,將主庫發來的bin log保存在本地,然后從庫進行回放
## Innodb 事務為什么要兩階段提交?
* 先寫 redolog 后寫binlog。假設在 redolog 寫完,binlog 還沒有寫完的時候,MySQL 進程異常重啟,這時候 binlog 里面就沒有記錄這個語句。然后你會發現,如果需要用這個 binlog 來恢復臨時庫的話,由于這個語句的**「binlog 丟失」**,這個臨時庫就會少了這一次更新,恢復出來的這一行 c 的值就是 0,與原庫的值不同。
* 先寫 binlog 后寫 redolog。如果在 binlog 寫完之后 crash,由于 redolog 還沒寫,崩潰恢復以后這個事務無效,所以這一行c的值是0。但是 binlog 里面已經記錄了“把c從0改成1”這個日志。所以,在之后用 binlog 來恢復的時候就**「多了一個事務出來」**,恢復出來的這一行 c 的值就是 1,與原庫的值不同。
## 分布式事務
https://mp.weixin.qq.com/s/x0y0_NmA8rrWxhK-m7duVA
- 消息隊列
- 為什么要用消息隊列
- 各種消息隊列產品的對比
- 消息隊列的優缺點
- 如何保證消息隊列的高可用
- 如何保證消息不丟失
- 如何保證消息不會重復消費?如何保證消息的冪等性?
- 如何保證消息消費的順序性?
- 基于MQ的分布式事務實現
- Beanstalk
- PHP
- 函數
- 基礎
- 基礎函數題
- OOP思想及原則
- MVC生命周期
- PHP7.X新特性
- PHP8新特性
- PHP垃圾回收機制
- php-fpm相關
- 高級
- 設計模式
- 排序算法
- 正則
- OOP代碼基礎
- PHP運行原理
- zavl
- 網絡協議new
- 一面
- TCP和UDP
- 常見狀態碼和代表的意義以及解決方式
- 網絡分層和各層有啥協議
- TCP
- http
- 二面
- TCP2
- DNS
- Mysql
- 鎖
- 索引
- 事務
- 高可用?高并發?集群?
- 其他
- 主從復制
- 主從復制數據延遲
- SQL的語?分類
- mysqlQuestions
- Redis
- redis-question
- redis為什么那么快
- redis的優缺點
- redis的數據類型和使用場景
- redis的數據持久化
- 過期策略和淘汰機制
- 緩存穿透、緩存擊穿、緩存雪崩
- redis的事務
- redis的主從復制
- redis集群架構的理解
- redis的事件模型
- redis的數據類型、編碼、數據結構
- Redis連接時的connect與pconnect的區別是什么?
- redis的分布式鎖
- 緩存一致性問題
- redis變慢的原因
- 集群情況下,節點較少時數據分布不均勻怎么辦?
- redis 和 memcached 的區別?
- 基本算法
- MysqlNew
- 索引new
- 事務new
- 鎖new
- 日志new
- 主從復制new
- 樹結構
- mysql其他問題
- 刪除
- 主從配置
- 五種IO模型
- Kafka
- Nginx
- trait
- genergtor 生成器
- 如何實現手機掃碼登錄功能
- laravel框架的生命周期