天天看點

Mysql事務機制

事務機制解決問題:

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

事務四種屬性: 原子性 一緻性 隔離性 持久性

原子性

事務是一個或者多個SQL語句組成的整體,要麼全部執行成功,要麼全都執行失敗 ,事務執行之後,不允許停留在中間某個狀态.比如:把10部門中MANGER員工調往20部門,其他崗位員工調往30部門,然後删除10部門. 涉及到事務:開啟事務 UPDATE語句 DELETE語句 送出事務

Mysql事務機制

比如下邊三行代碼, 第一行開啟一個事務, 第二行代表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少錢.

Mysql事務機制

隔離性

  • 隔離性要求事務不受其他并發事務的影響, 如果同在給定的時間内,該事物是資料庫唯一運作的事務
  • 預設情況下A事務,隻能看到日志中該事物的相關資料
  • 預設情況下A事務,隻能看到該事物的相關資料
  • 除了預設情況下,想看别的事務内容? 請繼續往下看到隔離級别部分.

持久性

  • 事務一旦送出,結果便是永久性的,即便發生當機,仍然可以依靠事務日志完成資料的持久化

    事務的四個隔離級别

    剛才的隔離性上邊說,預設情況下隻看自己的,那麼想看别人的或者想看曾經自己的,或者設定一些事務之間的sql執行順序.那麼就需要調整隔離級别了.首先看一張表:

  • Mysql事務機制
  • 買票案例–利用未送出事務read uncommitted

    A去刷12306軟體買票, 看到還剩一個座位,拍了下來,正在付款, 此時B也看到了.也拍了下來,然後吧唧把錢付了.A則付款失敗了,傳回一看剛才的未售出狀态邊已售出了…這不耽誤事麼,半路殺出個程咬金.

  • Mysql事務機制
  • 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程序結束.

Mysql事務機制

A執行,但沒commit

Mysql事務機制

B 序列化設定的事務将挂着

Mysql事務機制