1. 程式人生 > 資料庫 >mysql事務學習

mysql事務學習

事務

mysql中,事務能保證業務的完整性,是使用者定義的一個數據操作序列,這些操作要麼全做,要麼全不做,是一個不可分割的工作單位。

例:銀行轉賬:
A 轉100元  給B
A賬戶   -100
B賬戶 	+100

出現錯誤,沒有一起成功,100元將無故丟失。

mysql控制事務

在 MySQL 中,事務的自動提交狀態預設是開啟的。

系統變數autocommit (用於控制是否自動提交事務)

  • autocommit = 1 :每條語句自動提交,立即生效。
  • autocommit = 0 :每條語句必須使用commit提交事務生效,使用rollback撤銷事務。
//檢視變數autocommit   --預設自動提交
mysql> select  @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+
1 row in set (0.00 sec)

//修改變數  --關閉自動提交
mysql> set autocommit=0;
Query OK, 0 rows affected (0.01 sec)

將自動提交關閉後,測試資料回滾:

INSERT INTO user VALUES (2, 'b', 1000);

-- 關閉 AUTOCOMMIT 後,資料的變化是在一張虛擬的臨時資料表中展示,
-- 發生變化的資料並沒有真正插入到資料表中。
SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |  1000 |
|  2 | b    |  1000 |
+----+------+-------+

-- 資料表中的真實資料其實還是:
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |  1000 |
+----+------+-------+

-- 由於資料還沒有真正提交,可以使用回滾
ROLLBACK;

-- 再次查詢
SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |  1000 |
+----+------+-------+

將虛擬的資料真正提交到資料庫中

INSERT INTO user VALUES (2, 'b', 1000);
-- 手動提交資料(永續性),
-- 將資料真正提交到資料庫中,執行後不能再回滾提交過的資料。
COMMIT;

-- 提交後測試回滾
ROLLBACK;

-- 再次查詢(回滾無效了)
SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |  1000 |
|  2 | b    |  1000 |
+----+------+-------+

手動開啟一個事務

基本操作說明
start transaction; / begin;(手動)開始事務
commit;結束事務,提交()全部完成
rollback結束事務,回滾(回到初始狀態)

autocommit = 1自動提交事務狀態下,不改變系統變數,手動開啟一個事務

BEGIN;
UPDATE user set money = money - 100 WHERE name = 'a';
UPDATE user set money = money + 100 WHERE name = 'b';

-- 由於手動開啟的事務沒有開啟自動提交,
-- 此時發生變化的資料仍然是被儲存在一張臨時表中。
SELECT * FROM user;
+----+------+-------+
| id | name | money |
+----+------+-------+
|  1 | a    |   900 |
|  2 | b    |  1100 |
+----+------+-------+

-- 提交資料
COMMIT;

-- 測試回滾(無效,因為表的資料已經被提交)
ROLLBACK;

事務的四大特性(ACID)

  • 原子性::事務中所有操作是不可再分割的原子單位。事務中所有操作要麼全部執行成功,要麼全部執行失敗。
  • 一致性:一致性代表了底層資料儲存的完整性。資料庫中只包含成功事務提交的結果;若其中包含失敗的結果,則其他成功也為失敗狀態。
  • 隔離性:隔離性是當多個使用者併發訪問資料庫時,比如操作同一張表時,資料庫為每一個使用者開啟的事務,不能被其他事務的操作所幹擾,多個併發事務之間要相互隔離。
  • 持續性:事務一旦結束 ( COMMIT ) ,就不可以再返回了 ( ROLLBACK ) 。永續性是指一個事務一旦被提交了,那麼對資料庫中的資料的改變就是永久性的,即便是在資料庫系統遇到故障的情況下也不會丟失。

資料庫併發可能會出現的問題

  • 髒讀(讀未提交):事務A讀取到了事務B執行,但是並沒有提交(commit)的事務,並且最終事務B開啟了回滾(rollback)回到了最初狀態
  • 不可重複讀(讀已提交):事務A讀取資料表中資料,進行操作,同時,事務B也操作這張表,並且對資料表進行了資料修改並提交,然後事務A操作表,發現結果與讀取到的表資訊前後不一致
  • 幻讀事務A和事務B同時操作一張表,事務A提交的資料,不能被事務B讀到,這就是幻讀。舉例:(系統管理員A將資料庫中所有學生的成績從具體分數改為ABCDE等級,但是系統管理員B就在這個時候插入了一條具體分數的記錄,當系統管理員A改結束後關閉事務發現還有一條記錄沒有改過來,就好像發生了幻覺一樣,這就叫幻讀。)

事務的隔離性可分為四種 ( 效能從低到高 ) :

  1. READ UNCOMMITTED ( 讀取未提交 )
    如果有多個事務,那麼任意事務都可以看見其他事務的未提交資料。

  2. READ COMMITTED ( 讀取已提交 )
    只能讀取到其他事務已經提交的資料。

  3. REPEATABLE READ ( 可被重複讀 )
    如果有多個連線都開啟了事務,那麼事務之間不能共享資料記錄,否則只能共享已提交的記錄。

  4. SERIALIZABLE ( 序列化 )
    所有的事務都會按照固定順序執行,執行完一個事務後再繼續執行下一個事務的寫入操作。(這意味著佇列中同時只能執行一個事務的寫入操作 )

檢視當前資料庫的預設隔離級別:

-- MySQL 8.x, GLOBAL 表示系統級別,不加表示會話級別。
SELECT @@GLOBAL.TRANSACTION_ISOLATION;
SELECT @@TRANSACTION_ISOLATION;
+--------------------------------+
| @@GLOBAL.TRANSACTION_ISOLATION |
+--------------------------------+
| REPEATABLE-READ                | -- MySQL的預設隔離級別,可以重複讀。
+--------------------------------+

-- MySQL 5.x
SELECT @@GLOBAL.TX_ISOLATION;
SELECT @@TX_ISOLATION;

修改隔離級別:

-- 設定系統隔離級別,LEVEL 後面表示要設定的隔離級別 (READ UNCOMMITTED)。
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

-- 查詢系統隔離級別,發現已經被修改。
SELECT @@GLOBAL.TRANSACTION_ISOLATION;
+--------------------------------+
| @@GLOBAL.TRANSACTION_ISOLATION |
+--------------------------------+
| READ-UNCOMMITTED               |
+--------------------------------+