MySQL數據庫干貨_21——MySQL事務【附有詳細代碼】
MySQL事務
事務簡介
事務是指作為單個邏輯工作單元執行的一系列操作,要么完全地執行,要么完全地不執行。
事務定義(Transaction)
- 事務是一個最小的不可再分的工作單元;通常一個事務對應一個完整的業務(例如銀行賬戶轉賬業務,該業務就是一個最小的工作單元)
- 一個完整的業務需要批量的DML(insert、update、delete)語句共同聯合完成
- 事務只和DML語句有關,或者說DML語句才有事務。這個和業務邏輯有關,業務邏輯不同,DML語句的個數不同
事務四大特征(ACID)
- 原子性(ATOMICITY)
事務中的操作要么都不做,要么就全做。
- 一致性(CONSISTENCY)
一個事務應該保護所有定義在數據上的不變的屬性(例如完整性約束)。在完成了一個成功的事務時,數據應處于一致的狀態。
- 隔離性(ISOLATION)
一個事務的執行不能被其他事務干擾。
- 持久性(DURABILITY)
一個事務一旦提交,它對數據庫中數據的改變就應該是永久性的。
事務類型
-
顯式事務
需要我們手動的提交或回滾。
DML 語言中的所有操作都是顯示事務操作。
-
隱式事務
數據庫自動提交不需要我們做任何處理,同時也不具備回滾性。DDL、DCL 語言都是隱式事務操作
使用事務
| TCL語句 | 描述 |
|---|---|
| start transaction | 事務開啟 |
| commit | 事物提交 |
| rollback | 事物回滾 |
示例一:
創建account賬戶表,包含id、卡號、用戶名、余額。
create table account(
id int primary key auto_increment,
cardnum varchar(20) not null,
username varchar(30) not null,
balance double(10,2)
);
示例二:
向account表中插入兩條數據。
insert into account(cardnum,username,balance)
VALUES('123456789','張三',2000);
insert into account(cardnum,username,balance)
VALUES('987654321','李四',2000);
示例三:
在一個事務中完成轉賬業務。
START TRANSACTION
update account set balance = balance-200 where cardnum = '123456789';
update account set balance = balance+200 where cardnum = '987654321';
select * from account;
--當我們關閉數據庫重新打開后,張三和李四的賬戶余額并沒發生任何變化。
--這是因為當我們使用“STARTTRANSACTION”開啟一個事務后,該事務的提交方式不再是自動的,
--而是需要手動提交,而在這里,我們并沒有使用事務提交語句COMMIT,
--所以對account表中數據的修改并沒有永久的保存到數據庫中,也就是說我們的轉賬事務并沒有執行成功
--提交轉賬事務
commit;
--事務的回滾讓數據庫恢復到了執行事務操作前的狀態。
--需要注意的是事務的回滾必須在事務提交之前,因為事務一旦提交就不能再進行回滾操作。
rollback;
事務的并發問題
臟讀(讀取未提交數據)
指一個事務讀取了另外一個事務未提交的數據。
A事務讀取B事務尚未提交的數據,此時如果B事務發生錯誤并執行回滾操作,那么A事務讀取到的數據就是臟數據。
不可重復讀(前后多次讀取,數據內容不一致)
在一個事務內讀取表中的某一行數據,多次讀取結果不同。
事務A在執行讀取操作,由整個事務A比較大,前后讀取同一條數據需要經歷很長的時間 。而在事務A第一次讀取數據,比如此時讀取了小明的年齡為20歲,事務B執行更改操作,將小明的年齡更改為30歲,此時事務A第二次讀取到小明的年齡時,發現其年齡是30歲,和之前的數據不一樣了,也就是數據不重復了,系統不可以讀取到重復的數據,成為不可重復讀。
幻讀(前后多次讀取,數據總量不一致)
是指在一個事務內讀取到了別的事務插入的數據,導致前后讀取數量總量不一致。
事務A在執行讀取操作,需要兩次統計數據的總量,前一次查詢數據總量后,此時事務B執行了新增數據的操作并提交后,這個時候事務A讀取的數據總量和之前統計的不一樣,就像產生了幻覺一樣,平白無故的多了幾條數據,成為幻讀。
事務的隔離級別
事務的隔離級別用于決定如何控制并發用戶讀寫數據的操作。數據庫是允許多用戶并發訪問的,如果多個用戶同時開啟事務并對同一數據進行讀寫操作的話,有可能會出現臟讀、不可重復讀和幻讀問題,所以MySQL中提供了四種隔離級別來解決上述問題。
事務的隔離級別從低到高依次為:
- READ UNCOMMITTED<最低>
- READ COMMITTED
- REPEATABLE READ
- SERIALIZABLE<最高>
隔離級別越低,越能支持高并發的數據庫操作。
查看MySQL默認事務隔離級別
SELECT @@transaction_isolation;
設置事務隔離級別
對當前session有效。
set session transaction isolation level read uncommitted;
set session transaction isolation level read committed;
set session transaction isolation level repeatable read;
set session transaction isolation level serializable;
浙公網安備 33010602011771號