6. MySQL -- 事務

目錄

事務

事務的概念

什麼是事務:

事務的四大特性

事務的應用場景說明

手動提交事務

手動提交事務的SQL語句

手動提交事務使用過程:

案例演示1:事務提交

案例演示2:事務回滾

自動提交事務

案例演示3:自動提交事務

取消自動提交

事務原理

原理圖:

事務的原理解釋:

回滾點

什麼是回滾點

回滾點的操作語句

具體操作:

事務小結

事務的隔離級別

事務的四大特性ACID

事務的隔離級別

MySQL數據庫有四種隔離級別

MySQL事務隔離級別相關的命令

髒讀的演示

不可重複讀的演示

幻讀的演示


事務

 

事務的概念

什麼是事務:

   一個業務操作,如:轉賬操作。需要執行多條SQL語句,如果有一條語句失敗,已經執行的語句必須進行回滾,要回到沒有執行前的狀態。要麼所有的語句全部執行成功,要麼就全部失敗,稱爲事務Transaction。

 

事務的四大特性

事務特性

含義

原子性(Atomicity

事務中所有的代碼必須是一個整體,要麼全部成功,要麼全部失敗。

一致性(Consistency

事務在執行前或執行後,數據庫的狀態必須保持一致。如轉賬前總金額與轉賬後總金額要相同。

隔離性(Isolation

如果同時有多個事務在數據庫中執行,事務與事務之間不能相互影響。

持久性(Durability

如果事務執行成功,對數據庫影響是持久的。

事務的應用場景說明

  • 轉賬的操作
-- 創建數據表
CREATE TABLE account (
    id INT PRIMARY KEY AUTO_INCREMENT,
    NAME VARCHAR(10),
    balance DOUBLE
);
-- 添加數據
INSERT INTO account (NAME, balance) VALUES ('Jack', 1000), ('Rose', 1000);
  • 轉賬需求:

模擬Jack給Rose轉500元錢,一個轉賬的業務操作最少要執行下面的2條語句:

Jack賬號-500

Rose賬號+500

-- 從jack中扣錢500塊

update account set balance=balance-500 where name='Jack';

-- 給rose加錢

update account set balance=balance+500 where name='Rose';

假設當Jack賬號上-500元,服務器崩潰了。Rose的賬號並沒有+500元,數據就出現問題了。我們需要保證其中一條SQL語句出現問題,整個轉賬就算失敗。只有兩條SQL都成功了轉賬纔算成功。這個時候就需要用到事務。

手動提交事務

MYSQL中可以有兩種方式進行事務的操作:

  1. 手動提交事務
  2. 自動提交事務

手動提交事務的SQL語句

功能

SQL語句

開啓事務

start transaction

提交事務

commit

回滾事務

rollback

手動提交事務使用過程:

 

案例演示1:事務提交

 

模擬Jack給Rose轉500元錢(成功) 目前數據庫數據如下:

  1. 使用DOS控制檯進入MySQL
  2. 執行以下SQL語句: 1.開啓事務, 2.Jack賬號-500, 3.Rose賬號+500
  3. 使用SQLYog查看數據庫:發現數據並沒有改變
  4. 在控制檯執行commit提交任務:
  5. 使用SQLYog查看數據庫:發現數據改變

案例演示2:事務回滾

 

模擬Jack給Rose轉500元錢(失敗)

  1. 在控制檯執行以下SQL語句:1.開啓事務, 2.Jack賬號-500
  2. 使用SQLYog查看數據庫:發現數據並沒有改變
  3. 在控制檯執行rollback回滾事務:
  4. 使用SQLYog查看數據庫:發現數據沒有改變

結論: 如果事務中SQL語句沒有問題,commit提交事務,會對數據庫數據的數據進行改變。 如果事務中SQL語句有問題,rollback回滾事務,會回退到開啓事務時的狀態。

自動提交事務

MySQL默認每一條DML(增刪改)語句都是一個單獨的事務,每條語句都會自動開啓一個事務,執行完畢自動提交事務,MySQL默認開始自動提交事務

案例演示3:自動提交事務

 

  1. 將金額重置爲1000
  2. 更新其中某一個賬戶
  3. 使用SQLYog查看數據庫:發現數據已經改變

取消自動提交

 

  • 查看MySQL是否開啓自動提交事務

在mysql中@@開頭,表示mysql中全局變量,可以直接使用

  • 取消自動提交事務

  • 執行更新語句,使用SQLYog查看數據庫,發現數據並沒有改變,在控制檯執行commit提交任務

事務原理

事務開啓之後, 所有的操作都會臨時保存到事務日誌中, 事務日誌只有在得到commit命令纔會同步到數據表中,其他任何情況都會清空事務日誌(rollback,斷開連接) 

原理圖:

 

事務的原理解釋:

 

  1. 用戶創建連接,創建日誌文件
  2. 如果用戶沒有開啓事務,所有的操作直接寫到數據庫中
  3. 如果開啓事務,所有增刪改操作寫到日誌文件中,並沒有寫到數據庫中。
  4. 如果進行了查詢操作,將表中的數據經過日誌文件加工以後返回。
  5. 如果執行commit命令,把日誌文件中的數據寫到數據庫
  6. 如果執行rollback命令,把日誌文件清空,數據並沒有寫到數據庫中。

回滾點

什麼是回滾點

之前我們所有的事務操作都是回滾到事務開始之前,有時我們並不希望回滾到最前面,可能只是回滾到其中的某個點,設置回滾點。不用回滾到最開始的狀態。

回滾點的操作語句

 

回滾點的操作語句

語句

設置回滾點

savepoint 名字

回到回滾點

rollback to 名字

具體操作:

 

  1. 將數據還原到1000
  2. 開啓事務
  3. 讓Jack賬號減2次錢,每次10塊
  4. 設置回滾點:savepoint two;
  5. 讓Jack賬號減2次錢,每次10塊
  6. 回到回滾點:rollback to two;
  7. 分析執行過程

事務小結

事務的操作

MySQL操作事務的語句

開啓事務

start transaction

提交事務

commit

回滾事務

rollback

查詢事務的自動提交情況

select @@autocommit

設置事務的自動提交方式

set @@autocommit = 0;  -- 手動提交

設置回滾點

savepoint 名字

回到回滾點

rollback to 名字

事務的隔離級別

事務的四大特性ACID

事務特性

含義

原子性(Atomicity

一個事務不可再分割,事務中所有的SQL語句是一個整體,要麼全部成功,要麼全部失敗。

一致性(Consistency

事務在操作數據之前與操作數據之後,數據庫的狀態應該是一致。如:轉賬前與轉賬後兩個人的總金額應該是一樣的。

隔離性(Isolation

事務與事務之間不應該相互影響,一個事務的執行不應該影響到另一個事務。

持久性(Durability

如果事務提交,它對數據庫的影響是持久的,就算服務器關閉,數據也是存在的。

事務的隔離級別

 

事務在操作時的理想狀態:

併發訪問的問題

含義

髒讀

一個事務讀取到了另一個事務中尚未提交的數據

不可重複讀

一個事務中兩次讀取的數據內容不一致,要求的是一個事務中多次讀取時數據是一致的,這是事務update時引發的問題

幻讀

一個事務中兩次讀取的數據的數量不一致,要求在一個事務多次讀取的數據的數量是一致的,這是insertdelete時引發的問題

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 級別字符串;

髒讀的演示

 

將數據進行恢復:UPDATE account SET balance = 1000;

  • 打開A窗口登錄MySQL,設置全局的隔離級別爲最低
mysql -uroot -proot
set global transaction isolation level read uncommitted;

  • 打開B窗口,AB窗口都開啓事務
use day23;
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窗口查詢賬戶,錢沒了

髒讀非常危險的,比如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提交事務

  • 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隔離級別,B窗口再次提交事務即可看到數據變化

幻讀的演示

 

我們可以將事務隔離級別設置到最高,以擋住幻讀的發生 將數據進行恢復:

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執行不了,可以擋住幻讀

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章