首頁 > 軟體

一文帶你瞭解MySQL中的事務

2023-02-20 06:01:27

一.什麼是事務

  • 在MySQL中的事務(Transaction)是由儲存引擎實現的,在MySQL中,只有InnoDB儲存引擎才支援事務。
  • 事務處理可以用來維護資料庫的完整性,保證成批的sQL語句要麼全部執行,要麼全部不執行。
  • 事務用來管理DDL、DML、DCL操作,比如insert,update,delete語句,預設是自動提交的。

比如:在銀行轉賬時,必須保證轉賬絕對安全,這時需要事務參與

 -- id為1的賬戶轉賬給id為2的賬戶
update account set money=money -200 where id=1;
update account set money=money +200 where id=2;

思考

假如在第一次update之後,出現了意外、異常,沒有執行第二次update,這時轉賬是否會出現異常?

二.事務操作

MySQL的事務操作主要有以下三種

1.開啟事務:start Transaction

  • 任何一條DML語句( insert、update、delete)執行,標誌事務的開啟
  • 命令:BEGIN 或 START TRANSACTION

2.提交事務:commit Transaction

  • 成功的結束,將所有的DML語句操作歷史記錄和底層硬碟資料來一次同步
  • 命令:COMMIT

3.回滾事務

  • 失敗的結束,將所有的DML語句操作歷史記錄全部清空
  • 命令:ROLLBACK

之前的所有SQL操作其實也有事務,只是MysQL自動幫我們完成的,每執行一條SQL時MySQL就幫我們自動提交事務,因此如果想要手動控制事務,則必須關閉MySQL的事務自動提交。

在MySQL中直接用SET來改變MySQL的自動提交模式:

演示

create database test_transaction;
use test_transaction;
 
create table account(
	id int primary key,
	name varchar(20),
	money double
 
);
 
insert into account values(1,'張三',1000),(2,'李四',1000);
 
-- 設定MySQL的事務為手動提交(關閉自動提交)
select @@autocommit;-- 輸出1指開啟
set autocommit=0;
 
-- 模擬賬戶轉賬
-- 開啟事務
begin;
update account set money=money -200 where id=1;
update account set money=money +200 where id=2;
-- 提交事務
commit;
 
-- 回滾事務
rollback;
 
select * from account a ;

不提交直接查詢的結果是

但是

在圖形上數位需要提交後才可以正常顯示

這是因為select查的是最新的記憶體上的變化

當開啟事務還未提交之前,執行回滾事務語句,那麼就會復原開啟事務中執行的語句

小結

begin開啟後要麼commit提交落盤要麼rollback回滾落盤,先執行開啟,在執行SQL語句,最後執行commit或者rollback

三.事務的特性

1.原子性

事務是一個不可分割的整體,事務開始後的所有操作,要麼全部完成,要麼全部不做

2.一致性

系統從一個正確的狀態,遷移到另一個正確的狀態

3.隔離性

每個事務的物件對其他事務的操作物件互相分離,事務提交前對其他事務不可見

4.永續性

事務一旦提交,則其結果是永久性的

四.事務的隔離級別

概述

lsolate,顧名思義就是將事務與另一個事務隔離開,為什麼要隔離呢?如果一個事務正在操作的資料被另一個事務修改或刪除了,最後的執行結果可能無法達到預期。如果沒有隔離性還會導致其他問題。

如上圖,越往上兩個事務之間的關聯程度越緊密,越往下越安全但效率越低。

四種隔離級別

1、讀未提交(Read uncommitted)

一個事務可以讀取另一個未提交事務的資料,最低階別,任何情況都無法保證,會造成髒讀。

2、讀已提交(Read committed)

一個事務要等另一個事務提交後才能讀取資料,可避免髒讀的發生,會造成不可重複讀。

3、可重複讀(Repeatable read)

就是在開始讀取資料(事務開啟)時,不再允許修改操作,可避免髒讀、不可重複讀的發生,但是會造成幻讀。

4、序列(Serializable)

是最高的事務隔離級別,在該級別下,事務序列化順序執行,可以避免髒讀、不可重複讀與幻讀。但是這種事務隔離級別效率低下,比較耗資料庫效能,一般不使用。

Mysql的預設隔離級別是Repeatable read

事務隔離級別髒讀不可重複讀幻讀
讀未提交(Read uncommitted)
讀已提交(Read committed)
可重複讀(Repeatable read)
序列(Serializable)

髒讀、不可重複讀、幻讀

髒讀:所謂的髒讀,其實就是讀到了別的事務回滾前的髒資料。比如事務B執行過程中修改了資料X,在未提交前,事務A讀取了X,而事務B卻回滾了,這樣事務A就形成了髒讀。

不可重複讀:事務A首先讀取了一條資料,然後執行邏輯的時候,事務B將這條資料改變了,然後事務A再次讀取的時候,發現資料不匹配了,就是所謂的不可重複讀了。

幻讀:事務A首先根據條件索引得到N條資料,然後事務B改變了這N條資料之外的M條或者增添了M條符合事務A搜尋條件的資料,導致事務A再次搜尋發現有N+M條資料了,就產生了幻讀。

不可重複讀和幻讀比較:

兩者有些相似,但是前者針對的是update或delete,後者針對的insert。

操作

-- 檢視隔離級別
show variables like '%isolation%';
 
-- 設定隔離級別
/*
 set session transaction isolation level 級別字串
 級別字串:read uncommitted、read committed、repeatable read、serializable
 */
 
-- 設定read uncommitted 
set session transaction isolation level read uncommitted;
-- 這種隔離級別會引起髒讀,A事務讀取到B事務沒有提交的資料
 
-- 設定read committed
set session transaction isolation level read committed;
-- 這種隔離級別會引起不可重複讀,A事務在沒有提交事務之前,可看到資料不一致
 
 
-- 設定repeatable read(MysQ預設的)
set session transaction isolation level repeatable read;
-- 這種隔離級別會引起幻讀,A事務在提交之前和提交之後看到的資料不一致
 
-- 設定serializable
set session transaction isolation level serializable;
-- 這種隔離級別比較安全,但是效率低,A事務操作表時,表會被鎖起,B事務不能操作。

到此這篇關於一文帶你瞭解MySQL中的事務的文章就介紹到這了,更多相關MySQL事務內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com