MySQL中的事務


1. 事務

1.1. 為什么需要事務

現在的很多軟件都是多用戶,多程序,多線程的,對同一個表可能同時有很多人在用,為保持數據的一致性,所以提出了事務的概念。

 

A B 要划錢,A 的賬戶-1000元, B 的賬戶就要+1000元,這兩個update 語句必須作為一個整體來執行,不然A 扣錢了,B 沒有加錢這種情況很難處理。

 

1.2. 什么存儲引擎支持事務

1.查看數據庫下面是否支持事務(InnoDB支持)?

  show engines;

 

2.查看mysql當前默認的存儲引擎?

  show variables like '%storage_engine%';

 

3.查看某張表的存儲引擎?

  show create table 表名 ;

 

4.對於表的存儲結構的修改?

建立InnoDB 表:Create table .... type=InnoDBAlter table table_name type=InnoDB;

 

1.3. 事務特性

事務應該具有4個屬性:原子性、一致性、隔離性、持久性。這四個屬性通常稱為ACID特性。

 

原子性(atomicity

一致性(consistency

隔離性(isolation

持久性(durability

 

1.3.1. 原子性(atomicity

一個事務必須被視為一個不可分割的最小單元,整個事務中的所有操作要么全部提交成功,要么全部失敗,對於一個事務來說,不可能只執行其中的一部分操作

 

老婆大人給Deer發生活費

1.老婆大人工資卡扣除500

2.Deer工資卡增加500

 

整個事務要么全部成功,要么全部失敗

 

1.3.2. 一致性(consistency

一致性是指事務將數據庫從一種一致性轉換到另外一種一致性狀態,在事務開始之前和事務結束之后數據庫中數據的完整性沒有被破壞

 

老婆大人給Deer發生活費

 

1.老婆大人工資卡扣除500

 

2.Deer工資卡增加500

2.Deer工資卡增加1000

 

扣除的錢(-500) 與增加的錢(500) 相加應該為0

 

1.3.3. 持久性(durability

一旦事務提交,則其所做的修改就會永久保存到數據庫中。此時即使系統崩潰,已經提交的修改數據也不會丟失

 

並不是數據庫的角度完全能解決

 

1.3.4. 隔離性(isolation

一個事務的執行不能被其他事務干擾。即一個事務內部的操作及使用的數據對並發的其他事務是隔離的,並發執行的各個事務之間不能互相干擾。

(對數據庫的並行執行,應該像串行執行一樣)

 

未提交讀(READ UNCOMMITED)臟讀

已提交讀 READ COMMITED)不可重復讀

可重復讀(REPEATABLE READ

可串行化(SERIALIZABLE

 

mysql默認的事務隔離級別為repeatable-read

show variables like '%tx_isolation%';

 

1.3.4.1. 事務並發問題

臟讀:事務A讀取了事務B更新的數據,然后B回滾操作,那么A讀取到的數據是臟數據

 

不可重復讀:事務 A 多次讀取同一數據,事務 B 在事務A多次讀取的過程中,對數據作了更新並提交,導致事務A多次讀取同一數據時,結果 不一致。

 

幻讀:系統管理員A將數據庫中所有學生的成績從具體分數改為ABCDE等級,但是系統管理員B就在這個時候插入了一條具體分數的記錄,當系統管理員A改結束后發現還有一條記錄沒有改過來,就好像發生了幻覺一樣,這就叫幻讀。

 

不可重復讀的和幻讀很容易混淆,不可重復讀側重於修改,幻讀側重於新增或刪除。解決不可重復讀的問題只需鎖住滿足條件的行,解決幻讀需要鎖表

 

 

1.3.4.2. 未提交讀(READ UNCOMMITED)臟讀

show variables like '%tx_isolation%';

set SESSION TRANSACTION ISOLATION LEVEL read UNCOMMITTED;

 

一個session

  start TRANSACTION

  update account set balance = balance -50 where id = 1

 

另外一個session中查詢

select * from account

 

回到第一個session中 回滾事務

ROLLBACK

 

在第二個session

select * from account

 

在另外一個session中讀取到了為提交的數據,這部分的數據為臟數據

 

1.3.4.3. 已提交讀 READ COMMITED)不可重復讀

 

show variables like '%tx_isolation%';

 

set SESSION TRANSACTION ISOLATION LEVEL read committed;

 

一個session

  start TRANSACTION

  update account set balance = balance -50 where id = 1

 

另外一個session中查詢 (數據並沒改變)

select * from account

 

回到第一個session中 回滾事務

commit

 

 

在第二個session中

select * from account (數據已經改變)

 

1.3.4.4. 可重復讀(REPEATABLE READ

show variables like '%tx_isolation%';

 

set SESSION TRANSACTION ISOLATION LEVEL repeatable read;

 

一個session

  start TRANSACTION

  update account set balance = balance -50 where id = 1

 

另外一個session中查詢 (數據並沒改變)

select * from account

 

回到第一個session中 回滾事務

commit

 

在第二個session中

select * from account (數據並未改變)

 

 

1.3.4.5. 可串行化(SERIALIZABLE

show variables like '%tx_isolation%';

 

set SESSION TRANSACTION ISOLATION LEVEL serializable;

 

 

1.開啟一個事務

begin

select * from account  發現3條記錄

 

 

2.開啟另外一個事務

begin

select * from account  發現3條記錄 也是3條記錄

 

insert into account VALUES(4,'deer',500)  發現根本就不讓插入

 

3.回到第一個事務 commit

 

 

1.1.1.1. 間隙鎖(gap鎖)

 其實在mysql中,可重復讀已經解決了幻讀問題,借助的就是間隙鎖

 

實驗1

select @@tx_isolation;

 create table t_lock_1 (a int primary key);

insert into t_lock_1 values(10),(11),(13),(20),(40);

 

 begin

 select * from t_lock_1 where a <= 13 for update;

 

 在另外一個會話中

insert into t_lock_1 values(21) 成功

insert into t_lock_1 values(19) 阻塞

 

rr隔離級別中者個會掃描到當前值(13)的下一個值(20,並把這些數據全部加鎖

 

實驗:2

 

create table t_lock_2 (a int primary key,b int, key (b));

insert into t_lock_2 values(1,1),(3,1),(5,3),(8,6),(10,8);

 

會話1

BEGIN

 select * from t_lock_2 where b=3 for update;

 

 

 

1 3 5 8 10

1 1 3 6 8

會話2

select * from t_lock_2 where a = 5 lock in share mode; -- 不可執行,因為a=5上有一把記錄鎖

insert into t_lock_2 values(4, 2); -- 不可以執行,因為b=2(1, 3]

insert into t_lock_2 values(6, 5); -- 不可以執行,因為b=5(3, 6)

insert into t_lock_2 values(2, 0); -- 可以執行,(2, 0)均不在鎖住的范圍內

insert into t_lock_2 values(6, 7); -- 可以執行,(6, 7)均不在鎖住的范圍內

insert into t_lock_2 values(9, 6); -- 可以執行

insert into t_lock_2 values(7, 6); -- 不可以執行

 

 二級索引鎖住的范圍是 (1, 3],(3, 6

 主鍵索引只鎖住了a=5的這條記錄 [5]

 

1.1. 事務語法

 

1.1.1. 開啟事務

1begin

2START TRANSACTION(推薦)

3begin work

 

1.1.2. 事務回滾  

rollback

 

1.1.3. 事務提交

  commit

 

1.1.4. 還原點

savepoint

show variables like '%autocommit%';  自動提交事務是開啟的

 

set autocommit=0;    //關閉事務自動提交

 

insert into testdemo values(5,5,5);

savepoint s1;

insert into testdemo values(6,6,6);

savepoint s2;

insert into testdemo values(7,7,7);

savepoint s3;

 

 

select * from testdemo

rollback to savepoint s2

 

rollback


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM