[TOC] 簡介 說明 Transaction Control Language 事務控制語言 事務 事務由單獨單元的一個或一組sql語句組成的一個執行單元,這個執行單元要麼全部執行,要麼全部不執行。 拓展 Mysql中的存儲引擎 在mysql中的數據用各種不同的技術存儲在文件(記憶體)中 通過 sh ...
目錄
簡介
說明
Transaction Control Language 事務控制語言
事務
事務由單獨單元的一個或一組sql語句組成的一個執行單元,這個執行單元要麼全部執行,要麼全部不執行。
拓展
Mysql中的存儲引擎
- 在mysql中的數據用各種不同的技術存儲在文件(記憶體)中
- 通過 show engines; 命令來查看Mysql支持的存儲引擎
在Mysql中用的最多的存儲引擎:innodb,MyISAM,memory等。其中 innodb 支持事務,而 myisam、memory等不支持事務
delete和truncate在事務使用時的區別
- delete支持事務回滾
truncate不支持事務回滾
事務的ACID()屬性
### 原子性(Atomicity)
原子性是指事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生一致性(Consistency)
事務必須使資料庫從一個一致性狀態變換到另外一個一致性狀態
隔離性(Isolation)
事務的隔離性是指一個事務的執行不能被其它事務干擾,即一個事務內部的操作及使用的數據對併發的其它事務是隔離的,併發執行的各個事務之間不能相互干擾。
持久性(Durability)
持久性是指一個事務一旦被提交,它對資料庫中數據的改變就是永久性的,接下來的其它操作和資料庫故障不應該對其有任何影響
案例
轉賬:
馬 雲:1000元
馬化騰:1000元
馬雲向馬化騰轉賬500元,簡單 sql 如下:
update 表 set 餘額=500 where name='馬雲';
update 表 set 餘額=1500 where name='馬化騰';
如果上面兩條sql,再馬雲的餘額減少 500 的情況下,資料庫掛了,如果沒有事務控制的話,馬雲的錢就變成了 500,馬化騰還是 1000。
事務的創建
隱式事務
介紹
事務沒有明顯的開啟和關閉。
例如:insert、update、delete
通過查看變數,執行命令:
show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
可查看,自動提交為 開啟 狀態,這樣的話,執行增、刪、改語句時,預設開啟了事務,如果操作的是一組sql(多條sql),隱形事務就沒用了。
顯式事務
介紹
事務具有明顯的開啟和結束的標記,使用顯式事務的話,前提需要把 autocommit 關閉
關閉autocommit
mysql> set autocommit = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | OFF |
+---------------+-------+
語法
步驟1:開啟事務
set autocommit = 0;
start transaction; # 可選的
步驟2:編寫事務中的sql語句
語句1;
語句2;
.............
步驟3:結束事務
commit; 提交事務
rollback; 回滾事務
演示
提交事務:
set autocommit = 0;
start transaction;
update user_info set `password` = 'qqqqqqq' where id = 1;
update user_info set `password` = 'wwwwwww' where id = 2;
commit;
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0
Query OK, 0 rows affected (0.00 sec)
mysql> select * from user_info where id in (1,2);
+----+-----------+----------+--------+---------------------+---------------------+
| id | user_name | password | status | create_time | update_time |
+----+-----------+----------+--------+---------------------+---------------------+
| 1 | liuyang | qqqqqqq | 1 | 2019-09-07 14:38:47 | 2019-09-07 14:38:47 |
| 2 | zhangsan | wwwwwww | 1 | 2019-09-07 14:38:47 | 2019-09-07 14:38:47 |
+----+-----------+----------+--------+---------------------+---------------------+
2 rows in set (0.06 sec)
回滾事務:
set autocommit = 0;
start transaction;
update user_info set `password` = 'xxxxxxx' where id = 1;
update user_info set `password` = 'aaaaaaa' where id = 2;
rollback;
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
Query OK, 0 rows affected (0.00 sec)
mysql> select * from user_info where id in (1,2);
+----+-----------+----------+--------+---------------------+---------------------+
| id | user_name | password | status | create_time | update_time |
+----+-----------+----------+--------+---------------------+---------------------+
| 1 | liuyang | qqqqqqq | 1 | 2019-09-07 14:38:47 | 2019-09-07 14:38:47 |
| 2 | zhangsan | wwwwwww | 1 | 2019-09-07 14:38:47 | 2019-09-07 14:38:47 |
+----+-----------+----------+--------+---------------------+---------------------+
2 rows in set (0.08 sec)
由上可見,如果開啟了事務,修改命令執行成功後,結果會存在 記憶體 中,只有commit了之後才會寫進磁碟中進行持久化。
同時運行多個事務
對於同時運行多個事務,當這些事務訪問 資料庫中相同的數據 時,如果沒有採取必要的隔離機制,就會導致各種併發問題:
臟讀:對於兩個事務T1、T2,T1讀取了已經被T2更新但還 沒有被提交 的欄位之後,若T2回滾,T1讀取的內容就是臨時且無效的。
不可重覆讀:對於兩個事務T1、T2,T1讀取了一個欄位,然 後 T2 更新了該欄位之後,T1再次讀取了同一個欄位,值就不同了
幻讀:對於兩個事務T1、T2,T1從一個表中讀取了一個欄位,然後T2在該表中插入了一些新的行之後,如果T1再次讀取同一個表,就會多出幾行
資料庫事務的隔離性: 資料庫系統必須具有隔離併發運行各個事務的能力,使它們不會相互影響,避免各種併發問題。
一個事務與其他事務隔離的程度稱為隔離級別: 資料庫規定了多種事務隔離級別,不同隔離級別對應不同的干擾程度,隔離級別越高,數據一致性就越好,但併發性越弱
四種事務隔離級別
隔離級別 | 描述 |
---|---|
READ UNCOMMITTED (讀未提交數據) | 允許事務讀取未被其他事務提交的變更,臟讀,不可重覆讀和幻讀的問題都會出現 |
READ COMMITED (讀已提交數據) | 只允許事務讀取已經被其他事務提交的變更,可以避免臟讀,但不可重覆讀和幻讀問題仍然可能出現 |
REPEATABLE READ (可重覆讀) | 確保事務可以多次從一個欄位中讀取相同的值,在這個事務持續期間,禁止其它事務對這個欄位進行更新,可以避免臟讀和不可重覆讀,但幻讀的問題仍然存在 |
SERIALIZABLE (串列化) | 確保事務可以從一個表中讀取相同的行,在這個事務持續期間,禁止其他事務對該表執行插入,更新和刪除操作,多有併發問題都可以避免,但性能十分低下。 |
Oracle支持2中事務隔離級別:READ COMMITED和SERIALIZABLE。Oracle預設的事務隔離級別為:READ COMMITED
Mysql支持4種事務隔離級別,Mysql預設的事務隔離級別為:REPEATABLE READ
演示事務的隔離級別
臟讀
圖1
圖2
圖3:圖1 進行了 rollback
圖4:再次查詢圖2
不可重覆讀
圖1
設置資料庫事務級別為 read-committed(讀已提交數據)
修改數據,讓這個事務處於未提交狀態
圖2
開啟一個新事務
圖3
圖4:再次查詢圖2
發現數據已經更改,由此說明,read-committed事務中,如果T1事務未提交時查詢T2事務中的數據時,避免了臟讀,但是如果在T1事務已提交,T2事務再次查詢時候,發現上一次查詢結果數據已經改變(不可重覆讀)。由此可見,read-committed事務中也有可能出現臟讀情況,只是相比 read-uncommitted事務會好些。
可重覆讀
圖1
圖2
由此可見,這個事務級別沒有臟讀
圖3
圖4
由此可見,repeatable read事務級別可解決臟讀和不可重覆讀
幻讀
圖1
圖2
圖3
解決辦法:事務隔離級別修改為最高級(serializabel),修改為最高級別的話,T1開啟事務修改數據,T2如果此時插入數據的話,會阻塞(加了鎖,等待狀態,如果等待時間長,就會超時),等到T1提交了事務,T2會繼續執行。
事務級別總結
事務級別 | 臟讀 | 幻讀 | 不可重覆讀 |
---|---|---|---|
read uncommitted | √ | √ | √ |
read committed | × | √ | √ |
repeatable read | × | √ | × |
serializabel | × | × | × |
命令
# 查看隔離級別
select @@tx_isolation;
# 設置隔離級別【session:當前,global:全局】
set session | global transaction isolation level 隔離級別;
Mysql和Oracle預設事務
Mysql中預設的是 repeatable read;
Oracle中預設的是 read committed
回滾點
savepoint 節點,這是保存點