【數據庫之美】數據庫事務隔離級別

-- 創建數據表
CREATE TABLE account (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10),
balance DOUBLE
);
-- 添加數據
INSERT INTO account (NAME, balance) VALUES ('zhangsan', 1000), ('lisi', 1000);

事務的原理:

事務開啓之後, 所有的操作都會臨時保存到事務日誌中, 事務日誌只有在得到 commit 命令纔會同步到數據表中,其他任何情況都會清空事務日誌(rollback,斷開連接)

  1. 客戶端連接數據庫服務器,創建連接時創建此用戶臨時日誌文件
  2. 開啓事務以後,所有的操作都會先寫入到臨時日誌文件中
  3. 所有的查詢操作從表中查詢,但會經過日誌文件加工後才返回
  4. 如果事務提交則將日誌文件中的數據寫到表中,否則清空日誌文件。

回滾點:

在某些成功的操作完成之後, 後續的操作有可能成功有可能失敗, 但是不管成功還是失敗, 前面操作都已經成
功, 可以在當前成功的位置設置一個回滾點。可以供後續失敗操作返回到該位置, 而不是返回所有操作, 這個點稱
之爲回滾點。
設置回滾點 savepoint 名字
回到回滾點 rollback to 名字
在這裏插入圖片描述

總結:設置回滾點可以讓我們在失敗的時候回到回滾點,而不是回到事務開啓的時候

事務的隔離級別

概念:多個事務之間隔離的,相互獨立的。但是如果多個事務的操作同一批數據,則會引發一些問題,設置不同級別就可以解決問題。

1.髒讀:一個事務,讀取到另一個事務中沒有提交的數據。

set global transaction isolation level read uncommitted;//設置最低隔離級別
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> update account set balance=balance-500 where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update account set balance=balance+500 where id=2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> rollback;
Query OK, 0 rows affected (0.09 sec)

髒讀危險 在不自動提交事務的時候 張三給趙四轉錢, 趙四收到後,張三進行回滾,會造成數據不一致現象。根本是事務的處理級別。
出現了讀未提交。將隔離級別進行升級到讀已提交

解決方案

set global transaction isolation level read committed;//設置讀已提交
select @@tx_isolation //查看隔離界別
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> update account set balance = balance-500 where id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update account set balance = balance+500 where id = 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

2.不可重複讀(虛讀):在同一個事務中,兩次讀取到的數據不一樣。

set global transaction isolation level read committed;//設置讀已提交
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from account;
+----+----------+---------+
| id | NAME     | balance |
+----+----------+---------+
|  1 | zhangsan |    1000 |
|  2 | lisi     |    1000 |
+----+----------+---------+
2 rows in set (0.00 sec)

mysql> select * from account;
+----+----------+---------+
| id | NAME     | balance |
+----+----------+---------+
|  1 | zhangsan |    1000 |
|  2 | lisi     |    1500 |
+----+----------+---------+
2 rows in set (0.00 sec)

mysql>  兩次讀取到的數據不一致。

解決方案

set global transaction isolation level repeatable read;//將隔離級別設置到可重讀讀

3.幻讀:一個事務操作DML數據表中所有記錄,另一個事務添加一條記錄,則第一個事務查詢不到自己的修改

隔離級別:
1.read uncommitted:讀未提交
問題:髒讀 不可重複讀 幻讀
2.read committed 讀已提交(oracle)
問題:不可重複讀 幻讀
3.repeatable read 可重複讀(mysql默認)
問題:幻讀
4.serializable 串行化
可以解決所有問題
注意:隔離級別從小到大安全性越來越高,但是效率越來越低
數據庫查詢隔離級別
select @@tx_isolation;
數據庫設置隔離界別
set global transaction isolation level 級別字符串;

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章