事務(mysql)
第一章 事務概念
1、事務機制在程式開發程序中有著很大的作用,在現實生活中,經常進行轉賬操作,分為兩個步驟:轉入與轉出,只有當兩部分都完成才認為轉賬成功,
2、如果其中任意操作例外沒有執行成功,則會導致兩賬戶的金額不同步,造成錯誤,為了避免上述錯誤,資料庫引入事務,
3、事務:就是對資料庫的一組操作,可以為一潭訓多條 sql 執行,其特點:要么都做,要么都不做,
在資料庫中使用事務時,必須先開啟事務,命令如下:
start transaction;
事務開啟后就可以執行 sql 陳述句,sql 陳述句執行完成后,需要相應陳述句來提交事務,可使用如下命令來結束事務:
#提交
commit;
#回滾
rollback;
sql 陳述句是自動提交的,事務需要手動提交:commit
如果不想提交事務,可通過 rollback 來回滾事務,使事務結束,
已提交的事務不能回滾
案例操作:
創建表:
create table account(
id int primary key auto_increment,
name varchar(40),
money float
);
#插入資料
insert into account(name,money) values('a',100);
insert into account(name,money) values('b',100);

演示事務操作:
-
首先開啟事務
-
start transaction;
-
-
轉賬
-
update account set money=money-10 where name='a'; update account set money=money+10 where name='b';
-
-
提交事務
-
commit;
-
通過 a 賬戶向 b 賬戶轉入 10元,結果如下:

注意:當 update 中出現錯誤,會導致事務不執行,這樣保證了事務的同步性,
而事務有嚴格的定義,必須滿足 4 個特性:
原子性(atomicity)- 指一個事務必須視為一個不可分割的最小作業單元,當事務中所有的操作完成后,才算整個事務執行成功,事務中有一條 sql 失敗,則執行成功的 sql 也必須撤銷,資料庫的狀態回退到執行事務前的狀態
一致性(consistency)- 指事物將資料庫從一種狀態轉換為另一種狀態;例如事務執行失敗,資料庫回退到執行事務前的狀態,
隔離性(isolation)- 也稱并發控制、可串性化、鎖等,指事務各自執行,互不干擾
持久性(durability)- 事務操作一旦提交,其修改的資料就會永久保存在資料庫中,
第二章 事務提交
事務操作最后需要手動提交,這個程序為確認程序,
例如在第一章 中 a賬戶向 b 賬戶轉賬了 10元,現在反過來
start transaction;
update account set money=money+10 where name='a';
update account set money=money-10 where name='b';
執行上述命令,后查看資料

上述事務沒有提交|回滾操作,這樣會導致資料只是臨時修改,當重新登錄資料庫后,資料庫中沒有改變,如下:

發現資料沒有修改,因為事務需要手動提交,下面為手動提交后的結果:(重新登錄資料庫)
start transaction;
update account set money=money+10 where name='a';
update account set money=money-10 where name='b';
commit;

所以事務一定需要提交,否則事務操作是暫時的,
第三章 事務回滾
在操作事務時,發現當前事務中的操作不合理,此時只要事務還沒有提交,就可以通過 回滾 來取下事務.
案例操作:a賬戶向 b 賬戶轉賬 10元
start transaction;
update account set money=money-10 where name='a';
update account set money=money+10 where name='b';
上述命令沒有提交命令,也就是事務沒有提交
執行結果如下:

可以看出轉賬操作成功執行,但此時 a 不想轉賬了,這時由于事務還沒提交,所以可以撤銷上述操作,通過如下命令:
rollback;
上述命令執行后結果如下所示:

可發現轉賬操作撤銷了,
第四章 事務隔離級別
資料庫是多執行緒并發訪問的,所以很容易出現多個執行緒同時開啟事務的情況,這樣會出現以下情況:
- 臟讀
- 重復讀
- 幻讀
- ......
為了避免情況的發生,需要設定事務隔離級別,
mysql 中的隔離級別有如下 4 種:
read uncommitted:讀未提交- 最低級別
- 該級別下的事務會讀取到另一事務中未提交的資料,稱為:臟讀(dirty read),這是很危險的,所以很少用
read committed:讀已提交- 大多資料庫管理系統的默認隔離級別,如 oracle
- 該級別下的事務只能讀取其他事務已經提交的內容
- 可避免臟讀,但不能避免 不可重復讀、幻讀,
- 不可重復讀:指事務內重復讀取別的執行緒已經提交的資料,但兩次讀取的結果不一致,原因是查詢程序中其他事務做了更新操作,
- 幻讀:指在一個事務內兩次查詢中資料條數不一致,原因是查詢程序中其他事務做了添加操作,
- 不可重復讀與幻讀嚴格上說不是錯誤,但其情況不符合實際需求,
repeatable read:可重復讀- MySQL 的默認事務隔離級別
- 避免臟讀、不可重復讀問題
- 會出現幻讀情況
- 確保同一事務的多個實體在并發讀取資料時,看到的是相同的資料
serializable:可串行化- 事務的最高隔離級別
- 會對事務強制排序,使其不發生沖突
- 解決臟讀、幻讀、不可重復讀問題,
- 實際上就是在讀資料時,進行加鎖操作,可能導致大量的超時現象和鎖爭
4.1、臟讀演示
臟讀:一個事務讀取了另外一個事務未提交的資料,
如 a 向 b 進貨,a開啟事務執行下述操作:
start transaction;
update account set money=money-10 where name='a';
update account set money=money+10 where name='b';
這時,a中的事務沒有提交,通知 b 查詢賬戶,而 b 的隔離級別低,就會讀取到 a 中未提交的資料,b發現賬戶增加了 10元,于是向 a 發貨,等 b 發貨后,a 回滾事務,此時 b 就會虧損,如下操作演示上述問題:
1、設定 b 中的事務隔離級別
mysql 中默認隔離級別為repeatable read:可重復讀,
這里設定其隔離級別為:read uncommitted:
set session transaction isolation level read uncommitted;
session:當前會話
transaction:事務
isolation:隔離
level:級別
read uncommitted:當前隔離級別
查詢事務隔離級別為:
select @@transaction_isolation;# mysql8

可發現修改成功,
2、演示臟讀
b賬戶:先開啟一個事務,在其中查詢余額資訊

a賬戶:開啟事務,執行轉賬
start transaction;
update account set money=money-10 where name='a';
update account set money=money+10 where name='b';

b賬戶:查詢賬戶余額

發現賬戶顯示錢已到帳,可以發貨,當發貨后,a賬戶回滾事務,這樣 b賬戶就會虧損
當 b賬戶設定隔離級別為:讀已提交 后,再次執行上述操作,發現 b賬戶中沒有變化,


4.2、演示不可重復讀
指事務中兩次查詢結果不一致,原因是查詢程序中其他事務做了更新操作,
例如:銀行統計報表期間,第一次 a賬戶有 100元,第二次查詢 a賬戶有 99元,原因是統計期間 a賬戶取出了 10元,這樣會導致多次統計報表的結果不一致,
演示:
b賬戶:開啟事務,在事務中查詢賬戶余額資訊

a賬戶:直接修改資料,不用開啟事務

b賬戶:查詢資料:

當設定 b賬戶事務隔離級別為 :repeatable read;時,重復上述操作:


發現不變,
4.3、演示幻讀
指在一個事務中兩次查詢中資料條數不一致,因為其他事務做了插入操作
b賬戶:事務隔離級別設定為 :read committed;且查詢賬戶余額

a賬戶:直接插入,不用開啟事務

b賬戶:查詢

發現賬戶多資料
當需改b賬戶事務隔離級別為:重復讀,再次執行上述操作,結果如下,

發現結果一致,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/552892.html
標籤:MySQL
下一篇:返回列表
