事務的隔離級別
事務的四大特性acid
事務特性 含義
原子性(atomicity) 每個事務都不能再拆分,如果事務中有多條語句,它們應該是乙個整體。要麼全部成功,要麼全部失敗。
一致性(consistency) 事務執行前與事務執行後,資料庫的狀態應該是一致的。如:轉賬操作,轉賬前前與轉賬後兩個人的總金額應該是一樣的。
隔離性(isolation) 如果同時有多個事務在資料庫中執行,事務與事務之間應該互不影響。
永續性(durability) 事務一旦提交,對資料庫的影響是持久的,就算關閉伺服器。資料也是持久**存在。**
事務的隔離級別
事務在操作時的理想狀態:事務與事務之間不會有任何影響
併發訪問的問題 含義
髒讀 乙個事務讀取到了另乙個事務中尚未提交的資料
不可重複讀 乙個事務中兩次讀取的資料內容不一致,要求的是乙個事務中多次讀取時資料是一致的,這是事務update時引發的問題
幻讀 乙個事務中兩次讀取的資料的數量不一致,要求在乙個事務多次讀取的資料的數量是一致的,這是insert或delete時引發的問題
mysql資料庫有四種隔離級別
上面的級別最低,下面的級別最高。「是」表示會出現這種問題,「否」表示不會出現這種問題。
級別 名字 隔離級別 髒讀 不可重複讀 幻讀 資料庫預設隔離級別
1 讀未提交 read uncommitted 是 是 是
2 讀已提交 read committed 否 是 是 oracle和sql server
3 可重複讀 repeatable read 否 否 是 mysql
4 序列化 serializable 否 否 否
mysql事務隔離級別相關的命令
查詢全域性事務隔離級別
查詢隔離級別
-- select @@tx_isolation;
設定事務隔離級別,需要退出mysql再重新登入才能看到隔離級別的變化
設定隔離級別
-- set global transaction isolation level 級別字串;
轉賬的操作
-- 建立資料表
create table account (
id int primary key auto_increment,
name varchar(10),
balance double
);-- 新增資料
insert into account (name, balance) values ('jack', 1000), ('rose', 1000);
髒讀的演示
將資料進行恢復:update account set balance = 1000;
開啟a視窗登入mysql,設定全域性的隔離級別為最低
mysql -uroot -proot
set global transaction isolation level read uncommitted;
開啟b視窗,ab視窗都開啟事務
use db;
start transaction;
a視窗更新2個人的賬戶資料,未提交
update account set balance=balance-500 where id=1;
update account set balance=balance+500 where id=2;
b視窗查詢賬戶
select * from account;
a視窗回滾
rollback;
b視窗查詢賬戶,錢沒了
select * from account;
髒讀非常危險的,比如jack向rose購買商品,jack開啟事務,向rose賬號轉入500塊,
然後打**給rose說錢已經轉了。
rose一查詢錢到賬了,發貨給jack。
jack收到貨後回滾事務,rose的再檢視錢沒了。
解決髒讀的問題:將全域性的隔離級別進行提公升
將資料進行恢復:
update account set balance = 1000;
在a視窗設定全域性的隔離級別為*read committed*
set global transaction isolation level read committed;
b視窗退出mysql,b視窗再進入mysql
ab視窗同時開啟事務 !
a更新2個人的賬戶,未提交
update account set balance=balance-500 where id=1;
update account set balance=balance+500 where id=2;
b視窗查詢賬戶
a視窗commit提交事務
commit;
b視窗檢視賬戶
結論:read committed的方式可以避免髒讀的發生卻有不可重複讀的問題
不可重複讀的演示
將資料進行恢復:
update account set balance = 1000;
開啟a視窗
set global transaction isolation level read committed;
開啟b視窗,在b視窗開啟事務
start transaction;
select * from account;
在a視窗開啟事務,並更新資料
start transaction;
update account set balance=balance+500 where id=1;
commit;
b視窗查詢
select * from account;
兩次查詢輸出的結果不同,到底哪次是對的?不知道以哪次為準。
很多人認為這種情況就對了,無須困惑,當然是後面的為準。
我們可以考慮這樣一種情況,比如銀行程式需要將查詢結果分別輸出到電腦螢幕和發簡訊給客戶,
結果在乙個事務中針對不同的輸出目的地進行的兩次查詢不一致,導致檔案和螢幕中的結果不一致,
銀行工作人員就不知道以哪個為準了。
解決不可重複讀的問題:
將全域性的隔離級別進行提公升為:repeatable read
將資料進行恢復:
update account set balance = 1000;
a視窗設定隔離級別為:*repeatable read*
set global transaction isolation level repeatable read;
b視窗退出mysql,b視窗再進入mysql
start transaction;
select * from account;
a視窗更新資料
start transaction;
update account set balance=balance+500 where id=1;
commit;
b視窗查詢
select * from account;
結論:同乙個事務中為了保證多次查詢資料一致,必須使用*repeatable read*隔離級別
幻讀的演示
我們可以將事務隔離級別設定到最高,以擋住幻讀的發生 將資料進行恢復:
update account set balance = 1000;
開啟a視窗
set global transaction isolation level serializable; -- 設定隔離級別為最高
a視窗退出mysql,a視窗重新登入mysql
start transaction;
select count(*) from account;
再開啟b視窗,登入mysql
在b視窗中開啟事務,新增一條記錄
start transaction; -- 開啟事務
insert into account (name,balance) values ('laowang', 500);
在a視窗中commit提交事務,b視窗中insert語句會在a視窗事務提交後立馬執行
在a視窗中接著查詢,發現資料不變
select count(*) from account;
b視窗中commit提交當前事務
a視窗就能看到最新的資料
結論:使用serializable隔離級別,乙個事務沒有執行完,其他事務的sql執行不了,可以擋住幻讀
事務的隔離級別舉例 事務的隔離級別
乙個事務是乙個完整的業務邏輯單元,不能再分,要麼全部執行成功,要麼全部失敗。比如 a給b轉賬100元,a的銀行卡就會少100元,b的銀行卡就會多100元,整個過程要麼全部執行成功,要麼全部失敗。a 原子性。事務是最小的業務邏輯單元。b 一致性。乙個事務必須保證多條dml語句同時成功或失敗。c 隔離性...
事務的隔離級別舉例 JDBC 事務隔離級別
本文總結了 jdbc 事務隔離級別。事務隔離級別定義了在乙個事務中,哪些資料是對當前執行的語句 可見 的。在併發訪問資料庫時,事務隔離級別定義了多個事務之間對於同個目標資料來源訪問時的可交叉程度。可交叉程度可分為以下幾類。可交叉程度 dirty reads 髒讀 當乙個事務能看見另外乙個事務未提交的...
事務的隔離級別舉例 JDBC事務隔離級別
一組要麼同時執行成功,要麼同時執行失敗的sql語句。是資料庫操作的乙個執行單元。斷開與資料庫的連線 表示乙個事務內的所有操作是乙個整體,要麼全部成功,要麼全部失敗 表示乙個事務內有乙個操作失敗時,所有的更改過的資料都必須回滾到修改前狀態 事務檢視資料時資料所處的狀態,要麼是另一併發事務修改它之前的狀...