天天看點

Mysql事件介紹

文章目錄

    • 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

隔離級别越高,問題越少,但是性能越差

繼續閱讀