1. 程式人生 > >MySQL事務概述-1

MySQL事務概述-1

事務是資料庫區別於檔案系統最重要的特性之一。事務可由一條非常簡單的SQL語句組成,也可以由一組複雜的SQL語句組成。事務是訪問並更新資料庫中各種資料項的一個程式執行單元。在事務操作中,要麼都做修改,要麼都不做,這就是事務的目的。

MySQL的儲存引擎中,INNODB支援事務特性,這裡主要講述INNODB的事務特性。

INNODB儲存引擎完全符合事務的ACID特性:

  • 原子性(atomicity)
  • 一致性(consistency)
  • 隔離性(isolation)
  • 永續性(durability)

原子性: 是指整個資料庫事務是不可分割的工作單位。只有使事務中所有的資料庫操作都執行成功,才能整個事務成功。事務中任何一個SQL語句執行失敗,已經執行成功的SQL語句必須撤銷,資料庫狀態應該退回到執行事務之前的狀態。事務是最小的工作單元,構成事務的DML語句,要麼全部執行成功,要麼全部失敗,這就是事務的原子性。

一致性: 在事務的執行前後,不能破壞資料庫的完整性約束條件。

隔離性:多個事務並行執行,一個事務的修改對其他事務是不可見的,好似是序列執行的。INNODB使用鎖來保證事務的隔離性。

永續性:事務一旦提交,所做的修改時持久的,不會因為資料庫的宕機,恢復等丟失事務的修改。

事務的分類(摘自Inside君的《MySQL技術內幕-INNODB儲存引擎》):

  • 扁平事務(float  transactions)
  • 帶有儲存點的扁平事務(flat transactions  with savepoint)
  • 鏈事務(Chained Transactions)
  • 巢狀事務(Nested Transactions)INNODB儲存引擎不支援
  • 分散式事務(Distributed Transactions)

扁平事務:是事務型別中最簡單的一種,但在實際中,用的最多。在扁平事務中,所有的操作都處於同一層次,其由begin開始,由commit或者rollback結束,其間操作是原子的,要麼都執行,要麼全部回滾。

#扁平事務的基本形式如下:
BEGINE  WORK;
operation1;
operation2;
.....
commit  OR  rollback

帶有儲存點的扁平事務: 在扁平事務中,事務中的SQL語句要麼全部執行,要麼全部回滾,但是有時operation1操作執行成功,operation2也執行了,這時候我們想回滾到operation1操作執行之後的狀態?引入了儲存點的概念,只要在operation1執行之後設定儲存點,回滾時指定對應的儲存點,就可以回滾到指定的儲存點的狀態:

mysql> select * from tb1;
+---+
| a |
+---+
| 1 |
| 2 |
| 4 |
+---+
3 rows in set (0.00 sec)

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

mysql> insert into tb1 select 5;
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> savepoint test1;       #設定儲存點1
Query OK, 0 rows affected (0.00 sec)

mysql> insert into tb1 select 7;
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> savepoint test2;       #設定儲存點2
Query OK, 0 rows affected (0.00 sec)

mysql> select * from tb1;
+---+
| a |
+---+
| 1 |
| 2 |
| 4 |
| 5 |
| 7 |
+---+
5 rows in set (0.00 sec)

mysql> rollback to test1;        #回滾到儲存點1
Query OK, 0 rows affected (0.00 sec)

mysql> select * from tb1;
+---+
| a |
+---+
| 1 |
| 2 |
| 4 |
| 5 |
+---+
4 rows in set (0.00 sec)

mysql>
儲存點例項

上面的例項中我們最先開始用begin開啟了一個事務,然後又回滾到了儲存點test1,需要注意的是這個事務並沒有結束,若需要結束需要執行commit或者rollback!

鏈事務:

儲存點事務的一種變種。儲存點事務在系統崩潰時,所有的儲存點都是易失的,即系統恢復時,事務需要從開始出重新執行,而不能從最近的儲存點繼續執行。

鏈事務指的是在提交事務時,釋放不需要的資料物件,將必要的處理上下文隱式地傳給下一個要開始的事務。提交事務和開始下一個事務將合併為一個原子操作。即下一個事務將看到上一個事務的結果,就好象在一個事務中進行一樣。

鏈事務與帶有儲存點的事務不同,帶有儲存點的事務能回滾到任意正確的儲存點。而鏈事務中的回滾僅限於當前儲存點。

鏈事務例項見下面:

巢狀事務

  是一個層次結構框架。由一個頂層事務控制各個層次的事務。頂層事務之下巢狀的事務被稱為子事務,其控制每一個區域性的變換。

巢狀事務的定義如下:

  1. 巢狀事務是由若干事務組成的一棵樹,子樹既可以是巢狀事務,也可以是扁平事務。
  2. 處在葉子節點的是扁平事務。但是每個事務從根到葉節點的距離可以是不同的。
  3. 位於根節點的事務稱為頂層事務,其他事務稱為子事務。事務的前驅稱為父事務,事務的下一層事務稱為兒子事務。
  4. 子事務既可以提交也可以回滾。但是它的提交操作並不馬上生效,除非其父事務已經提交,任何子事務都在頂層事務提交後才能真正的提交。
  5. 樹中的任意一個事務的回滾會引起它的所有子事務一同回滾,故子事務僅保留ACI特性,不具有D特性。

MySQL不支援巢狀事務。

分散式事務

  分散式事務是在分散式環境下執行的扁平事務。

事務控制語句

在MySQL的命令列預設設定下,事務都是自動提交的,即執行語句後就會馬上執行commit操作。

mysql> show variables like "autocommit";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.01 sec)

#預設情況自動提交時開啟的,可以設定為關閉。
#事務控制語句如下
  • start transaction | begin 顯式開啟一個事務。(在儲存過程中MySQL會自動將begin識別為begin....and,因此在儲存過程中開啟事務,需要使用start transaction)
  • commit | commit work    提交事務
  • rollba | rollback work 回滾事務
  • savepoint 建立儲存點
  • release savepoint identifier : 刪除一個儲存點,當儲存點不存在時,會報出異常
  • rollback to 【savepoint】 identifier: 回滾到某一個儲存點
  • set transaction leve xxxx: 設定事務的隔離級別

commit和commit work語句基本一致,都是用來提交事務。不同之處在於commit  work用來控制事務結束後的行為是chain還是release的。如果是chain,那麼就是鏈事務。

值(completion_type的取值) 描述
NO_CHAIN(或0) COMMIT並且 ROLLBACK 不受影響。這是預設值。
CHAIN (或1) commit和rollback之後,會自動開啟一個事務。
RELEASE(或2) commit和rollback之後,會終止當前會話的連線。

鏈事務例項:

mysql> select * from tb2;
+------+
| a    |
+------+
|   10 |
|   20 |
+------+
2 rows in set (0.00 sec)

mysql> set @@completion_type=1;               #設定為1
Query OK, 0 rows affected (0.00 sec)

mysql> begin;                                 #顯式開啟一個事務
Query OK, 0 rows affected (0.00 sec)

mysql> insert into tb2 select 30;             #插入數值30
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> commit;                                #提交事務
Query OK, 0 rows affected (0.00 sec)

mysql> insert into tb2 select 40;             #插入40
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> rollback;                              #回滾事務 
Query OK, 0 rows affected (0.00 sec)

mysql> select * from tb2;                     #結果看到只回滾了插入40的事務,也就是說上面的commit提交之後,又開啟了一個事務。 
+------+
| a    |
+------+
|   10 |
|   20 |
|   30 |
+------+
3 rows in set (0.00 sec)

mysql> 

當數值設定為2時:

mysql> set @@completion_type=2;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from tb2;
+------+
| a    |
+------+
|   10 |
|   20 |
|   30 |
+------+
3 rows in set (0.00 sec)

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

mysql> insert into tb2 select 40;
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> commit;                    #事務提交之後
Query OK, 0 rows affected (0.00 sec)

mysql> select @@version;          #再次查詢會有重新連線的提示,說明上次事務提交之後,斷開了當前會話的連線
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    86
Current database: mytest

+------------+
| @@version  |
+------------+
| 5.7.22-log |
+------------+
1 row in set (0.00 sec)

mysql>

對事物的操作統計

【待續】