mysql事務學習
阿新 • • 發佈:2020-12-05
事務
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改結束後關閉事務發現還有一條記錄沒有改過來,就好像發生了幻覺一樣,這就叫幻讀。)
事務的隔離性可分為四種 ( 效能從低到高 ) :
-
READ UNCOMMITTED ( 讀取未提交 )
如果有多個事務,那麼任意事務都可以看見其他事務的未提交資料。
-
READ COMMITTED ( 讀取已提交 )
只能讀取到其他事務已經提交的資料。
-
REPEATABLE READ ( 可被重複讀 )
如果有多個連線都開啟了事務,那麼事務之間不能共享資料記錄,否則只能共享已提交的記錄。
-
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 |
+--------------------------------+