事務機制解決問題:
- 避免寫入直接操作資料檔案,直接操作資料檔案是很危險的事,可以在确認無誤後同步進總庫.
- MySQL有5種日志檔案,其中隻有redo日志和undo日志與事物有關(5種日志檔案後續再說)
- 預設情況下,MySQL執行每條SQL語句都會自動開啟和送出事務
- 為了讓多條SQL語句納入一個事務下,可以手動管理事務

事務四種屬性: 原子性 一緻性 隔離性 持久性
原子性
事務是一個或者多個SQL語句組成的整體,要麼全部執行成功,要麼全都執行失敗 ,事務執行之後,不允許停留在中間某個狀态.比如:把10部門中MANGER員工調往20部門,其他崗位員工調往30部門,然後删除10部門. 涉及到事務:開啟事務 UPDATE語句 DELETE語句 送出事務
比如下邊三行代碼, 第一行開啟一個事務, 第二行代表sql語句,第三行代表要麼commit送出後疊加覆寫原始資料庫,要麼rollback取消這一過程所有操作.
START TRANSACTION;
SQL語句
[COMMIT | ROLLBACK];
備注:COMMIT:持久化送出 ; ROLLBACK:復原
舉個例子:
START TRANSACTION; -- 啟動事務機制
delete from t_emp; -- 增删改查過程
delete from t_dept; -- 增删改查過程
SELECT * FROM t_emp; -- 增删改查過程
SELECT * FROM t_dept; -- 增删改查過程
-- COMMIT; -- 送出同步(給注釋掉了)
ROLLBACK ; -- 復原不同步
事務一緻性
不管在任何給定的時間\并發事務有多少, 事務必須保證運作結果的一緻性,不允許資料歧義.比如銀行轉賬,100個人互相亂七八糟的轉賬,但最後總額肯定是固定的.原來總值100萬,經過一頓互相轉賬後,總額一定還是100萬,不能因為幾重了多錢,也不能因為bug少錢.
隔離性
- 隔離性要求事務不受其他并發事務的影響, 如果同在給定的時間内,該事物是資料庫唯一運作的事務
- 預設情況下A事務,隻能看到日志中該事物的相關資料
- 預設情況下A事務,隻能看到該事物的相關資料
- 除了預設情況下,想看别的事務内容? 請繼續往下看到隔離級别部分.
持久性
-
事務一旦送出,結果便是永久性的,即便發生當機,仍然可以依靠事務日志完成資料的持久化
事務的四個隔離級别
剛才的隔離性上邊說,預設情況下隻看自己的,那麼想看别人的或者想看曾經自己的,或者設定一些事務之間的sql執行順序.那麼就需要調整隔離級别了.首先看一張表:
-
買票案例–利用未送出事務read uncommitted
A去刷12306軟體買票, 看到還剩一個座位,拍了下來,正在付款, 此時B也看到了.也拍了下來,然後吧唧把錢付了.A則付款失敗了,傳回一看剛才的未售出狀态邊已售出了…這不耽誤事麼,半路殺出個程咬金.
- READ UNCOMMITTED 代表可以讀取其他事務未送出的資料
還是這個案例,如果B拍了正在付款,A看到的時候應該顯示已售出,就避免了竹籃子打水一場空, 淘寶下單同樣的場景.
怎麼用? 事務前加上 :SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SQL語言的話可以如下案例,注意讀裡面注釋
-- 案例一個
-- 事務A:開啟事務,把所有工資設定為1,但是沒送出(沒commit) ,此時查出來都是1元;
START TRANSACTION; -- 啟動事務機制
UPDATE t_emp SET sal=1;
SELECT sal FROM t_emp;
-- 此時開啟案例B,也來讀sal
SELECT empno , ename, sal FROM t_emp;
-- 讀出來的還是原來的工資資料.
-- 如果想要B讀取出A設定後的東西,則改成下邊代碼
-- B的結果:讀取A未送出的
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
START TRANSACTION;
SELECT empno , ename, sal FROM t_emp;
轉賬支出案例-- 利用committed
Scott賬務餘額5000,B先支出100, 此時A開啟進入系統,此時scott餘額4900. 緊接着此時A轉賬1000,此時應該scott餘額5900. 如果轉賬同時B又退回100,此時賬戶應該6000元.
但是如果不允許A讀取B的操作未送出的,就沒讀到支出又退回的100.A讀到5900塊,少了100. 這樣不對.大公司賬面複雜,這一天得差飛了.
READ COMMITTED 代表隻能讀取其他事務送出的資料
承接上邊的代碼部分案例,請閱讀備注
– 還是上邊案例,若A沒有送出commit 則B讀不到的話,則用這句話:注意是committed
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
SELECT empno , ename, sal FROM t_emp;
下單後,送出訂單前,商家提價了,按下單價支付案例–利用repeatable read
舉例場景 : A下單時候350 ,但沒付款. 正在猶豫時B商家把商品價格改高了到400. 過一會後A去付款還應該是付款350才對.
是以這個repeatable read 能讀取當時執行時讀到資料庫的資料,不受後續資料庫變化影響.
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
序列化事務–依次執行,未到執行時挂着
這個将把一切并發禁用, 讓事務逐一執行, 這會降低資料庫操作并發能力
開頭設定這句:SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
START TRANSACTION;
SELECT * FROM table1;
-- 若别的事務正在運作,這條将一直不出結果等待中
舉例:
A建立事務,修改了工資,但沒commit送出确認,總庫沒改呢.此時B查東西将被挂起. 若A執行了commit或者rollback,則B程序結束.
A執行,但沒commit
B 序列化設定的事務将挂着