# 一. 事務簡介 **事務是一組操作的集合,它是一個不可分隔的工作單位,事務會把所有的操作作為一個整體一起向系統提交或撤銷操作請求,即這些操作要麼同時成功,要麼同時失敗。** **就比如:張三給李四轉賬1000塊錢,張三銀行賬戶的錢減少了1000,而李四銀行賬戶的錢要增加1000。這一組操作就必須 ...
一. 事務簡介
事務是一組操作的集合,它是一個不可分隔的工作單位,事務會把所有的操作作為一個整體一起向系統提交或撤銷操作請求,即這些操作要麼同時成功,要麼同時失敗。
就比如:張三給李四轉賬1000塊錢,張三銀行賬戶的錢減少了1000,而李四銀行賬戶的錢要增加1000。這一組操作就必須在一個事務的範圍內,要麼都成功,要麼都失敗。
正常情況:轉賬這個操作,需要分為以下這麼三步來完成,三步完成之後,張三減少1000,而李四增加1000,轉賬成功:
異常情況:轉賬這個操作,也是分為以下這麼三步來完成,在執行第三步時報錯了,這樣就導致張三減少1000塊錢,而李四的金額沒變,這樣就造成了數據的不一致,就出現問題了。
為瞭解決上述的問題,就需要通過數據的事務來完成,我們只需要在業務邏輯執行之前開啟事務,執行完畢後提交事務。如果執行過程中報錯,則回滾事務,把數據恢復到事務開始之前的狀態。
註:預設MySQL的事務時自動提交的,也就是說,當執行完一條DML語句時,MySQL會立即隱式的提交事務。
二. 事務操作
數據準備:
drop table if exists account;
create table account(
id int primary key AUTO_INCREMENT comment 'ID',
name varchar(10) comment '姓名',
money double(10,2) comment '餘額'
) comment '賬戶表';
insert into account(name, money) VALUES ('張三',2000), ('李四',2000);
1. 未控制事務
(1). 測試正常情況
-- 1. 查詢張三餘額
select * from account where name = '張三';
-- 2. 張三的餘額減少1000
update account set money = money - 1000 where name = '張三';
-- 3. 李四的餘額增加1000
update account set money = money + 1000 where name = '李四';
測試完畢之後檢查數據的狀態,可以看出數據操作前後是一致的。
(2). 測試異常情況
-- 1. 查詢張三餘額
select * from account where name = '張三';
-- 2. 張三的餘額減少1000
update account set money = money - 1000 where name = '張三';
出錯了....
-- 3. 李四的餘額增加1000
update account set money = money + 1000 where name = '李四';
我們把數據都恢復到2000,然後再次一次性執行上述的SQL語句(出錯了... 這句話不符合SQL語法,執行就會報錯),檢查最終的數據情況,發現數據在操作前後不一致了。
2. 控制事務一
(1). 查看/設置事務提交方式
SELECT @@autocommit;
SET @@autocommit = 0;
(2). 提交事務
COMMIT;
(3). 回滾事務
ROLLBACK;
註:上述的這種方式,我們是修改了事務的自動提交行為,把預設的自動提交修改為了手動提交,此時我們執行的DML語句都不會提交,需要手動的執行commit進行提交。
3. 控制事務二
(1).開啟事務
START TRANSACTION 或 BEGIN ;
(2).提交事務
COMMIT;
(3).回滾事務
ROLLBACK;
轉賬案例:
-- 開啟事務
start transaction;
-- 1. 查詢張三餘額
select * from account where name = '張三';
-- 2. 張三的餘額減少1000
update account set money = money - 1000 where name = '張三';
-- 3. 李四的餘額增加1000
update account set money = money + 1000 where name = '李四';
-- 如果正常執行完畢, 則提交事務
commit;
-- 如果執行過程中報錯, 則回滾事務
-- rollback;
三. 事務四大特性
-
原子性(Atomicity):事務是不可分隔的最小操作單元,要麼全部成功,要麼全部失敗。
-
一致性(Consistency):事務完成時,必須使所有的數據都保持一致。
-
隔離性(Isolation):資料庫系統提供的隔離機制,保證事務在不受外部併發操作影響的獨立環境下運行。
-
持久性(Durability):事務一旦提交或回滾,它對資料庫中的數據的改變就是永久的。
上述就是事務的四大特性,簡稱ACID。
四. 併發事務問題
1. 臟讀:一個事務讀到另一個事務還沒有提交的數據
2. 不可重覆讀:一個事務先後讀取同一條記錄,但兩次讀取的數據不同,稱之為不可重覆讀
3. 幻讀:一個事務按照條件查詢數據時,沒有對應的數據行,但是在插入數據時,又發現這行數據已經存在,好像出現了”幻影”。
五. 事務隔離級別
為瞭解決併發事務所引發的問題,在資料庫中引入了事務隔離級別。主要有以下幾種:
隔離級別 | 臟讀(是否解決) | 不可重覆讀(是否解決) | 幻讀(是否解決) |
---|---|---|---|
讀未提交(Read uncommitted) | 未解決 | 未解決 | 未解決 |
讀已提交(Read committed) | 解決 | 未解決 | 未解決 |
可重覆讀(Repeatable Read)(預設) | 解決 | 解決 | 未解決 |
串列化(Serializable) | 解決 | 解決 | 解決 |
1. 查詢事務隔離級別
SELECT @@TRANSACTION_ISOLATION;
2. 設置事務隔離級別
SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
SESSION:session表示當前視窗的隔離級別。
GLOBAL:global表示全局的隔離級別
註:事務隔離級別越高,數據越安全,但是性能越低。
更多mysql學習請關註微信公眾號”雲哥技術yun3k”,回覆”mysql學習”,免費領取mysql全套學習資料。