文章目錄
-
- mysql中如何控制事務?
-
- 1. autocommit 自動送出
- 2. 使用begin 或者 start transaction來手動開啟一個事務
- 總結:事務四大特征ACID
- 事務隔離性
-
- 1. read uncommitted 讀未送出的,可能會出現髒讀
- 2. read committed 讀已送出的 可能會出現不可重複讀現象
- 3. repeatable read (**預設隔離級别**) 重複讀 可能出現幻讀
- 4. serializable 串行化
- 四種隔離級别的性能排列
概念:mysql中,事務是一個最小的不可分割的工作單元。事務能夠保證一個業務的完整性。
以銀行轉賬為例:
-- A支出100,B收款100
update user set money = money-100 where name = 'A';
update user set money = money+100 where name = 'B';
如果執行過程中隻有一條執行成功,另一條失敗,那麼系統資料就會出現錯誤。
是以在開發過程中,有時就要求多條sql語句,同時成功或者失敗(不可分割),這是事務要做的事情。
mysql中如何控制事務?
1. autocommit 自動送出
- mysql 預設是開啟的
select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 1 |
+--------------+
1 row in set (0.01 sec)
-- 自動送出:但我們去執行一個sql語句的時候,效果會立即提現,且不會復原
-- 事務復原值的是撤銷sql語句執行效果,
rollback;
-- 即執行之後,即使執行rollback;語句,也不會這小執行效果。
-- 要想取消操作,要設定autocommit = 0,關閉自動送出;
set autocommit = 0;
insert into user values(2,'b',100);
select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 2 | b | 100 |
+----+------+-------+
-- 再復原,那麼可以撤銷執行
rollback;
select * from user;
Empty set (0.00 sec)
-- 再次插入資料,并手動送出,再復原也不能撤銷
insert into user values(2,'b',100);
commit;
rollback;
select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 2 | b | 100 |
+----+------+-------+
1 row in set (0.00 sec)
以上例子說明自動送出能防止事務復原,從一方面說明,一旦送出(自動或者手動),那麼都 無法復原(持久性)。
綜上所述,事務包括:
- 自動送出 : @@autocommit=1;
- 手動送出:commit;
- 事務復原:rollback;
事務給我們提供了一個反悔的機會
回過頭來看轉賬,通過取消自動取消,在進行rollback可以取消操作
update user set money = money-100 where name = 'A';
update user set money = money+100 where name = 'B';
rollback;
2. 使用begin 或者 start transaction來手動開啟一個事務
begin;
update user set money = money-100 where name = 'A';
update user set money = money+100 where name = 'B';
rollback;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 1000 |
| 2 | b | 1000 |
+----+------+-------+
-- 把begin換成transaction可以達到同樣的效果。
-- 一旦commit, 那麼事務已經結束,rollback也沒用
總結:事務四大特征ACID
- A(atomic)原子性:事務是最小的機關,不可以分割
- C(consistency)一緻性:同一事務中的sql語句要同時成功或者同時失敗
- I(isolation):事務1和事務2之間是隔離的。
- D(durability)持久性:事務一旦結束(commit, rollback),就不可以傳回。
- 事務開啟方式:修改 autocommit =0,begin,transaction
- 事務結束方式:rollback,commit
事務隔離性
1. read uncommitted 讀未送出的,可能會出現髒讀
有事務A和事務B,操作過程中事務A沒有送出,事務B可以看到事務A的操作結果
首先來看如何看隔離級别
select @@global.transaction_isolation;
+--------------------------------+
| @@global.transaction_isolation |
+--------------------------------+
| REPEATABLE-READ |
+--------------------------------+
1 row in set (0.01 sec)
修改隔離級别
set global transaction isolation level read uncommitted;
select @@global.transaction_isolation;
+--------------------------------+
| @@global.transaction_isolation |
+--------------------------------+
| READ-UNCOMMITTED |
+--------------------------------+
1 row in set (0.00 sec)
小明向店鋪轉賬800
start transaction;
update user set money = money-800 where name = '小明';
update user set money = money+800 where name = '店鋪';
店鋪查賬是否到賬
但是小明這時候選擇rollback
此時店鋪主人重新查賬
select * from user; -- by 店鋪
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 900 |
| 2 | b | 1100 |
| 3 | 小明 | 1000 |
| 4 | 店鋪 | 1000 |
+----+------+-------+
4 rows in set (0.00 sec)
這裡店鋪和小明開啟了兩個不同的事務B和A,如果事務A(小明)開啟之後,他的未送出資料可以被其他(店鋪)使用者讀取,這樣就會出現髒讀,開發中不允許出現髒讀
2. read committed 讀已送出的 可能會出現不可重複讀現象
先是修改隔離級别,類似上面的
小張
start transaction;
select * from user;
+----+------+-------+
| id | name | money |
+----+------+-------+
| 1 | a | 900 |
| 2 | b | 1100 |
| 3 | 小明 | 1000 |
| 4 | 店鋪 | 1000 |
+----+------+-------+
小王
start transaction;
insert into user values(5,'c',100);
commit;
小張
select avg(money) from user;
+------------+
| avg(money) |
+------------+
| 820.0000 |
這裡小張看到平均值不是之前自己看到的,之前是1000。
雖然隻能讀到送出的資料,但是讀取同一張的資料可能前後不一緻(兩個人操作)。
這也叫做不可重複讀現象
3. repeatable read (預設隔離級别) 重複讀 可能出現幻讀
修改隔離級别和前面類似
張三:
王五:
張三:
insert into user values(6,'d',1000);
commit;
王五:
張三在送出之後,王五那邊不能夠即使相似,當王五也插入6号資料的時候,就會報錯,因為資料已經存在,但是因為repeatable read的隔離王五看不到。這就叫做幻讀
事務A和事務B同時操作一張表,事務A送出的資料也不能被事務B讀到,可能造成幻讀
4. serializable 串行化
張三:
王五:
張三:
insert into user values(7,'e',1000);
commit;
王五:
start transaction;
select * from user;
-- 能看到7号使用者已經存在
張三:
start transaction;
insert into user values(8,'f',1000);
-- 語句會被卡住
**當資料表被另外的事務操作的時候,其他事務裡面的寫操作是不可以操作,或者說會進入排隊等待,**直到其他事務結束的時候,要在沒有等待逾時的情況下。
他的問題在于性能最低
四種隔離級别的性能排列
READ-UNCOMMITTED > READ-COMMITTED > REPEATABLE-READ > SERIALIZABLE
隔離級别越高,問題越少,但是性能越差