1. 程式人生 > 實用技巧 >SQL中的事務

SQL中的事務

目錄

1、概述
---1.1事務是什麼?
---1.2例子:銀行轉賬業務
---1.3四個特徵ACID
---1.4和事務有關的兩條SQL語句(TCL)
---1.5事務開啟和結束的標誌

2、事務的提交和回滾的演示
---2.1事務的提交
---2.2事務的回滾
---2.3手動設定事務開關

3、事務的隔離級別
---3.1read uncommitted 讀未提交(級別最低)
---3.2read committed 讀已提交
---3.3repeatable read 可重複讀
---3.4serializable 序列化(序列化)
---3.5檢視隔離級別
---3.6設定隔離級別
---3.7隔離級別不一致性問題的關係

概述

事務是什麼?

1、一個最小的不可再分的工作單元;
2、通常一個事務對應一個完整的業務;(如:銀行轉賬業務)
3、而一個完整的業務需要批量的DML(insert、update、delete)語句共同完成;
4、事務只和DML語句有關係,或者說只有DML語句才有事務(保證資料的安全性);
5、以上所描述的批量DML語句共有多少DML語句,這個和業邏輯有關係,業務邏輯不同DML語句個數不同 。
6、一些關鍵詞:
1、開啟事務:start transaction
2、結束事務:end transaction
3、提交事務:commit transaction
4、回滾事務:rollback transaction

例子:銀行轉賬業務

1、銀行轉賬業務:是一個完整的業務,最小的單元,不可再分。
2、act-001(50000.0)轉10000.0給act-002(10000.0),操作如下:

update t_act set balance = 40000.0 
where actno = ‘act-001’;
update t_act set balance = 20000.0 
where actno = ‘act-002’;

3、分析
a)以上兩條DML語句必須同時成功或者同時失敗,因為它為最小業務單元,不可拆分;
b)當第一條DML語句執行成功之後,並不能將底層資料庫中的第一個賬戶的資料修改,只是將操作記錄了一下,這個記錄是在記憶體中完成的;
c)當第二條DML語句執行成功之後,和底層資料庫檔案中的資料完成同步。
d)若第二條DML語句執行失敗,將清空所有的歷史操作記錄。
結論:要完成以上功能,必須藉助事務(transaction)。

四個特徵ACID

1、原子性(Atomicity)
事務是最小單元,不可再分;
2、一致性(Consistency)
事務要求所有的DML語句操作的時候,必須保證同時成功或同時失敗;
3、隔離性(Isolation)
一個事務不會影響其它事務的執行;
4、永續性(Durability)
在事務完成之後,該事務對資料庫所作的更改將持久地儲存在資料庫中,並不會被回滾。

和事務有關的兩條SQL語句(TCL)

1、COMMIT; 提交
2、ROLLBACK; 回滾

事務開啟和結束的標誌
  • 開啟的標誌
    任何一條DML語句執行,標誌事務的開啟。
  • 結束的標誌
    提交(commit)或者回滾(rollback)
    1、提交:成功的結束,將所有的DML語句操作記錄和底層硬碟檔案中資料進行一次同步。
    2、回滾:失敗的結束,將所有DML語句操作記錄全部清空。
  • 重點
    1、在事務進行過程中,未結束之前,DML語句是不會修改底層資料庫檔案中的資料。
    2、只是將歷史操作記錄一下,在記憶體中完成記錄。
    3、只有在事務成功結束的時候才會修改底層硬碟檔案中的資料。

事務的提交和回滾的演示

  • 自動提交事務
    在MySQL資料庫管理系統中,預設情況下,事務是自動提交的。也就是說,叧要執行一條DML語句,就開啟了事務,並且提交了事務。
事務的提交
  • 第一步:start transaction; 手動開啟事務;
  • 第二步:DML語句…. 執行批量DML語句;
INSERT INTO t_user(`name`) 
VALUES('lisi');
INSERT INTO t_user(`name`) 
VALUES('zhaoliu');
SELECT * FROM t_user;

當前視窗可以檢視剛剛插入的資料:

其它視窗則看不見:

  • 第三步:commit; 手動提交事務(事務成功結束)。

    提交後都能看見:
事務的回滾
  • 第一步:start transaction;手動開啟事務
  • 第二步:DML語句…..批量DML語句
INSERT INTO t_user(`name`) 
VALUES('jack');
INSERT INTO t_user(`name`) 
VALUES('rose');
SELECT * FROM t_user;

當前視窗:

其它視窗:

  • 第三步:rollback;手動回滾事務(事務失敗結束)

    其它視窗:
手動設定事務開關

1、兩種關閉自動提交事務
a)set autocommit = off;
b)set session autocommit = off;

set autocommit = off;
show variables like '%commit%';


2、兩種開啟自動提交事務
a)set autocommit = on;
b)set session autocommit = on;

set autocommit = on;
show variables like '%commit%';


注意:以上開啟或關閉事務只對當前視窗有效。
3、查詢事務狀態:show variables like '%commit%';

事務的隔離級別

事務四個特性ACID之一:隔離性(isolation)

  • 隔離性有四個隔離級別:
    1、read uncommitted 讀未提交
    2、read committed 讀已提交
    3、repeatable read 可重複讀
    4、serializable 序列化
read uncommitted 讀未提交(級別最低)

1、事務A和和事務B,事務A未提交的資料,事務B可以讀取;
2、這裡讀取到的資料可以叫做“髒資料”或“髒讀 Dirty Read”;
3、讀未提交隔離級別最低,這種級別一般叧在理論上存在,資料庫預設隔離級別一般都高於該隔離級別。

read committed 讀已提交

1、事務A和事務B,事務A提交的資料,事務B才可讀取到;
2、該隔離級別高於“讀未提交”級別;
3、換句話說:對方事務提交之後的資料,當前事務才可讀取到;
4、該隔離級別可以避免髒資料;
5、該隔離級別能夠導致“不可重複讀取”(只能讀到對方事務提交之後的資料(更新後的),不能讀到原來的資料);
6、Oracle資料庫管理系統預設隔離級別為:讀已提交。

repeatable read 可重複讀

1、事務A和事務B,事務A提交之後的資料,事務B讀取不到;
2、事務B是可重複讀到資料的;
3、這種隔離級別高於“讀已提交”;
4、換句話說,對方提交之後的資料,還是讀取不到;
5、這種隔離級別可以避免“髒讀和不可重複讀”,達到“重複讀取”;
6、MySQL資料庫管理系統預設隔離級別為:可重複讀;
7、雖然可以達到“可重複讀”效果,但是會導致“幻象讀”(只能讀到原來的資料)。

serializable 序列化(序列化)

1、事務A和事務B,事務A在操作資料庫表中資料的時候,事務B只能排隊等待(解決了以上所有問題,但是效率太低);
2、這種事務隔離級別一般很少使用,吞吐量太低,使用者體驗不好;
3、這種隔離級別可以避免“幻象讀”,每一次讀取都是資料庫表中真實的記錄;
4、事務A和事務B不再併發。

檢視隔離級別
  • 檢視當前會話級隔離級別
    select @@session.transaction_isolation;
  • 檢視當前全域性隔離級別:
    select @@global.transaction_isolation;
設定隔離級別
  • 事務隔離級別的作用範圍分為兩種:會話級、全域性級
    1、會話級(session):只對當前會話有效。
    2、全域性級(global):對所有會話有效。
  • 例子
    SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED 事務隔離級別
    事務隔離級別:
    --- READ UNCOMMITTED
    --- READ COMMITTED
    --- REPEATABLE READ
    --- SERIALIZABLE
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED
select @@global.transaction_isolation;

隔離級別不一致性問題的關係
隔離級別 髒讀 不可重複讀 幻象讀
讀未提交
讀已提交 ×
可重複讀 × ×
序列化 × × ×