>[info]事務,是現實生活中的一組邏輯操作單元,這組操作要么全部成功,要么全部失敗
例子:轉賬
張三-500元
李四+500元
**事務的特性(ACID)**
- 原子性(automicity):事務不可再分割,要么全執行,要么全不執行。實現主要基于undo log(回滾日志文件)
- 一致性(consistency):執行事務會是數據從一個一致狀態切換到另一個一致狀態
- 隔離性(isolation):事務執行不受其他事務的干擾。實現主要基于鎖機制、數據的隱藏列、undo log和類next-key lock機制
- 持久性(durability):事務一旦提交,將永久改變數據庫數據。實現主要基于redo log(重做日志文件)
兩個并發事務一定會出現“臟讀”,即讀到的數據不準確
<br/>
## 6.1 臟讀、不可重復讀和幻讀
首先來看并發情況下,讀操作可能存在的三類問題:
- (1)臟讀:當前事務(A)中可以讀到其他事務(B)未提交的數據(臟數據),這種現象是臟讀。
舉例如下(以賬戶余額表為例):
```
事務A和B在T1時刻同時開啟事務;
事務B在T2時修改“張三”余額由100變為200;
事務A在T3時查詢“張三”的余額,結果為200【臟讀】(因為事務B還沒有提交事務)
事務B在T4時提交事務
```
- (2)不可重復讀:在事務A中先后兩次讀取同一個數據,兩次讀取的結果不一樣,
這種現象稱為不可重復讀。臟讀與不可重復讀的區別在于:前者讀到的是其他事務未提交的數據,
后者讀到的是其他事務已提交的數據。舉例如下:
```
事務A和B在T1時刻同時開啟事務;
事務A在T2時查詢“張三”的余額,結果為100修改“張三”余額由100變為200;
事務B在T3時修改“張三”余額由100變為200;
事務B在T4時提交事務
事務A在T5時查詢“張三”的余額,結果為200【不可重復讀】(兩次讀到的數據不一樣)
```
- (3)幻讀:在事務A中按照某個條件先后兩次查詢數據庫,兩次查詢結果的條數不同,
這種現象稱為幻讀。不可重復讀與幻讀的區別可以通俗的理解為:前者是數據變了,
后者是數據的行數變了。舉例如下:
```
事務A和B在T1時刻同時開啟事務;
事務A在T2時查詢0<id<5的所有用戶的余額,結果只查到“張三:100(id=1)”;
事務B在T3時向余額表中插入新用戶:李四:200(id=2);
事務B在T4時提交事務;
事務A在T5時再次查詢0<id<5的所有用戶的余額,結果查到“張三:100(id=1) 李四:200(id=2)“【幻讀】(不應該查到李四)
```
<br>
## 6.2 事務的創建
>隱式事務:事務沒有明顯的開啟和結束的標記
比如insert、update、delete語句,會自動開啟事務
delete from 表 where id =1;
> 顯式事務:事務具有明顯的開啟和結束的標記
> 前提:必須先設置自動提交功能為禁用
> 在自動提交模式下,如果沒有 start transaction 顯式地開始一個事務,
> 那么每個 sql 語句都會被當做一個事務執行提交操作。
(1). 開啟事務
```
set autocommit=0;
start transaction;(可選)
```
(2).編寫事務的sql語句
(3).結束事務
```
commit;
rollback;
```
>[success]mysql 的默認隔離級別為:repeatable read 可重復讀
Oracle的默認隔離級別為:read committed 讀 已提交
隔離級別(isolation)
| | 臟讀 | 不可重復讀 | 幻讀 | 第一類丟失更新 | 第二類丟失更新
| :-- | :-: | :-: | :-: | :-: | :-: |
| read uncommitted | √ | √ | √ | × | √ |
| read committed | × | √ | √ | × | √ |
| repeatable eead | × | × | √ | × | × |
| serializable | × | × | ×| × | × |
查看隔離級別
`select @@tx_isolation;(以后看到tx,要知道它表示事務的意思)
`
設置隔離級別
```
set session|global transaction isolation level 隔離級別;
session 會話,表示設置的隔離級別只在當前會話中有效;
global 全局,表示設置的隔離級別在所有的會話中都有效(但是其他需要重啟一次會話,不然其他的會話加載的內容會是設置全局級別之前的內容)
```
比如:打開瀏覽器輸入百度,就表示 你與瀏覽器開始了一個會話,關閉窗口就結束本次會話。
再比如,你打開cmd,輸入命令,就表示開啟了與命令行的會話
<br>
數據庫引擎:
**MyISAM引擎**,不支持事務;只支持表鎖。
**innoDB引擎**支持事務,也支持表鎖和行鎖
>行鎖:當兩個不同事務操作同一個數據(并發執行),前一個事務還沒有結束事務(提交或回滾),后一個事務就無法執行操作(會陷入等待狀態)
>表鎖:與行鎖功能相同,但是不限于當前行的數據,而是整個表的其他數據都不能修改(除非當前事務結束)
行鎖開銷大,粒度小,并發性好;表鎖開銷小,粒度大,并發性差