mysql 事務理解及相關操作

一、Mysql表引擎

  • Myisam:

Mysql 5.5 版本之前的默認表引擎
不支持事務
不支持外鍵
提供 表鎖

存儲數據時,會將數據存儲在三個文件中:一個文件存數據,一個文件存結構,一個文件存索引

  • innodb:

支持事務
支持外鍵
提供 行鎖

存儲數據時,會將數據存儲在兩個文件中:一個文件存數據和索引,一個文件存結構
查詢速度相對較慢

二、事務(Transaction)的概述

  1. MySQL 事務主要用於處理操作量大,複雜度高的數據。
  2. 在 MySQL 中只有使用了 Innodb 數據庫引擎 的數據庫或表才支持事務。
  3. 事務是一個不可再分的工作單元;通常將一組有序的增刪改操作看做一個獨立的執行單元,當這一組所有的操作都成功,事務執行成功,如果其中有一個操作失敗,事務執行回滾
  4. 在 MySQL 命令行的默認設置下,事務都是自動提交的,即執行 SQL 語句後就會馬上執行 COMMIT 操作。因此要顯式地開啓一個事務務須使用命令 BEGIN 或 START TRANSACTION,或者執行命令 SET AUTOCOMMIT=0,用來禁止使用當前會話的自動提交

三、事務的四大特性(ACID)

  1. 原子性(Atomicity): 事務被作爲最小的執行單元,不可分割。一個事務(transaction)中的所有操作,要麼全部完成,要麼全部不完成,不會結束在中間某個環節。
  2. 一致性(Consistency): 在事務開始之前和事務結束以後,數據庫的完整性沒有被破壞。即寫入的資料必須完全符合所有的預設規則。
  3. 隔離性(Isolation): 多個用戶併發訪問數據庫時,數據庫會給每個用戶開啓一個事務,事務和事務之間相互隔離,互不影響。隔離性可以防止多個事務併發執行時由於交叉執行而導致數據的不一致。
    事務隔離分爲不同級別,包括讀未提交(Read uncommitted)讀已提交(read committed)可重複讀(repeatable read)串行化(Serializable)
  4. 持久性(Durability): 一旦事務執行成功,對於數據的修改會被永久性的存儲在數據庫中

四、事務的四種隔離級別

4.1、 如果事務沒有隔離性,會導致以下情況:

  • 髒讀: 一個事務使用了 另一個未提交事務的數據;
  • 不可重複讀:一個事務重複讀取 一條數據,另一個事務修改了這條數據,導致兩次讀取的結果不一樣;
  • 幻讀: 一個事務讀取了多條數據並做了操作(統計,計算),另一個事務修改了其中一條數據,導致操作結果不一樣,就像出現了幻覺一樣。

4.2、 事務存在隔離性的話,會有以下四種隔離級別,隔離級別越高效率越低。

- Read uncommit: 讀未提交:最低的隔離級別  可能會發生任何情況  
  • 事物A和事物B,事物A未提交的數據,事物B可以讀取到
  • 這裏讀取到的數據叫做“髒數據”
  • 這種隔離級別最低,這種級別一般是在理論上存在,數據庫隔離級別一般都高於該級別
  • Read commit: 讀已提交:可以避免髒讀
  • 事物A和事物B,事物A提交的數據,事物B才能讀取到
  • 這種隔離級別高於讀未提交
  • 換句話說,對方事物提交之後的數據,我當前事物才能讀取到
  • 這種級別可以避免“髒數據”
  • 這種隔離級別會導致“不可重複讀取”
  • Oracle默認隔離級別
  • Repeatable read: 可重複讀: 可以避免髒讀和 不可重複讀
  • 事務A和事務B,事務A提交之後的數據,事務B讀取不到
  • 事務B是可重複讀取數據
  • 這種隔離級別高於讀已提交
  • 換句話說,對方提交之後的數據,我還是讀取不到
  • 這種隔離級別可以避免“不可重複讀取”,達到可重複讀取
  • 比如1點和2點讀到數據是同一個
  • MySQL默認級別
  • 雖然可以達到可重複讀取,但是會導致“幻讀”
  • Serializable: 串行化 ,最高隔離級別,可以避免任何情況發生
  • 事務A和事務B,事務A在操作數據庫時,事務B只能排隊等待
  • 這種隔離級別很少使用,吞吐量太低,用戶體驗差
  • 這種級別可以避免“幻讀”,每一次讀取的都是數據庫中真實存在數據,事務A與事務B串行,而不併發

五、事務隔離級別操作

1、設置事務隔離級別

  • 方法一:在my.ini文件中使用transaction-isolation選項來設置服務器的缺省事務隔離級別。

READ-UNCOMMITTED
READ-COMMITTED
REPEATABLE-READ
SERIALIZABLE

例如:
[mysqld]
transaction-isolation = READ-COMMITTED
  • 方法二:通過命令動態設置隔離級別。

隔離級別也可以在運行的服務器中動態設置,應使用SET TRANSACTION ISOLATION LEVEL語句。

SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL <isolation-level>  

其中的<isolation-level>可以是:
READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ
SERIALIZABLE

例如: SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

2、隔離級別的作用範圍

•   事務隔離級別的作用範圍分爲兩種: 
–   全局級:對所有的會話有效 
–   會話級:只對當前的會話有效 

•   例如,設置會話級隔離級別爲READ COMMITTED :
mysql> SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
或:
mysql> SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

•   設置全局級隔離級別爲READ COMMITTED : 
mysql> SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;

3、查看隔離級別

查看當前會話隔離級別
SELECT @@tx_isolation;

查看系統當前隔離級別
select @@global.tx_isolation;

六、事務操作的語句

  • START TRANSACTION或BEGIN:顯式地開啓一個事務;
  • COMMIT:會提交事務,並使對數據庫進行的所有修改成爲永久性的;
  • ROLLBACK:回滾會結束用戶的事務,並撤銷正在進行的所有未提交的修改;
  • SAVEPOINT point名稱:是事務過程中的一個邏輯點,用於取消部分事務,當結束事務時,會自動的刪除該事務中所定義的所有保存點。當執行rollback時,通過指定保存點可以回退到指定的點。在相應的事務操作組裏,保存點的名稱必須是唯一的;
  • RELEASE SAVEPOINT point名稱:刪除一個事務的保存點,當沒有指定的保存點時,執行該語句會拋出一個異常;
  • ROLLBACK TO point名稱:把事務回滾到標記點;

1、提交操作

mysql> start transaction;#手動開啓事務
mysql> insert into user(name) values('王五');
mysql> commit;#commit之後即可改變底層數據庫數據
mysql> select * from user;
+----+------+
| id | name |
+----+------+
|  1 | 張三  |
|  2 | 李四  |
|  3 | 王五  |
+----+------+
3 rows in set (0.00 sec)

2、回滾操作

mysql> start transaction;
mysql> insert into user(name) values('趙六');
mysql> rollback;
mysql> select * from user;
+----+------+
| id | name |
+----+------+
|  1 | 張三  |
|  2 | 李四  |
|  3 | 王五  |
+----+------+
3 rows in set (0.00 sec)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章