1. 程式人生 > >MySQL事務控制和鎖定語句

MySQL事務控制和鎖定語句

MySQL 支援對 MyISAM 和 MEMORY 儲存引擎的表進行表級鎖定,對 BDB 儲存引擎的表進行頁級鎖定,對 InnoDB 儲存引擎的表進行行級鎖定。預設情況下,表鎖和行鎖都是自動獲得的,不需要額外的命令。但是在有的情況下,使用者需要明確地進行鎖表或者進行事務的控制,以便確保整個事務的完整性,這樣就需要使用事務控制和鎖定語句來完成。

1) LOCK TABLEUNLOCK TABLE

    LOCK TABLES 可以鎖定用於當前執行緒的表。如果表被其他執行緒鎖定,則當前執行緒會等待,直到可以獲取所有鎖為止。

    UNLOCK TABLES 可以釋放當前執行緒獲得的任何鎖定。當前執行緒執行另一個 LOCK TABLES 時,或當與伺服器的連線被關閉時,所有由當前執行緒鎖定的表被隱含的解鎖,具體語法如下

        LOCK TABLES

          tbl_name [AS alias] {READ [LOCAL]|[LOW_PRIORITY] WRITE}

          [,tbl_name [AS alias] {READ [LOCAL]|[LOW_PRIORITY] WRITE}] ...

        UNLOCK TABLES

2) 事務控制

  MySQL 通過 SET AUTOCOMMIT、START TRANSACTION、COMMIT 和 ROLLBACK 等語句支援本地事務,具體語法如下

    START TRANSACTION|BEGIN [WORK]

    COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]

    ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]

    SET AUTOCOMMIT={0|1}

    START TRANSACTION 或 BEGIN 語句可以開始一項新的事務。

    COMMIT 和 ROLLBACK 用來提交或者回滾事務

    CHAIN 和 RELEASE 子句分別用來定義在事務提交或者回滾之後的操作,CHAIN 會立即啟動一個新事物,並且和剛才的事務具有相同的隔離級別,RELEASE 則會斷開和客戶端的連線。

    SET AUTOCOMMIT 可以修改當前連線的提交方式,如果設定了 SET AUTOCOMMIT = 0 ,則設定之後的所有事務都需要通過明確地命令進行提交或者回滾。

  • 預設情況下,MySQL是自動提交的,如果需要通過明確的 Commit 和 Rollback 來提交和回滾事務,那麼就需要通過明確地事務控制命令來開始事務,這是和 Oracle 的事務管理明顯不同的地方。如果應用是從 Oracle 資料庫遷移到 MySQL 資料庫,則需要確保應用中是否對事務進行了明確地管理。
  • 如果只是對某些語句需要進行事務控制,則使用 START TRANSACTION 語句開始一個事務比較方便,這樣事務結束之後可以自動回到自動提交的方式,如果希望所有事務都不是自動提交的,那麼通過修改 AUTOCOMMIT 來控制事務比較方便,這樣不用在每個事務開始的時候再執行 START TRANSACTION 語句。
  • 如果在鎖表期間用 START TRANSACTION  命令開始一個新事物,會造成一個隱含的 UNLOCK TABLES 被執行
  • 在同一個事務中,最好不使用不同儲存引擎的表,否則 ROLLBACK 時需要對非事務型別的表進行特別的處理,因為 COMMIT、ROLLBACK 只能對事務型別的表進行提交和回滾。
  • LOCK 方式加的表鎖,不能通過 ROLLBACK 進行回滾。
  • 通常情況下,只對提交的事務記錄到二進位制的檔案中,但是如果一個事務中包含非事務型別的表,那麼回滾操作也會被記錄到二進位制日誌中,以確保非事務型別表的更新可以被複制到從資料庫(Slave)中。
  • 和 Oracle 的事務管理相同,所有的 DDL 語句是不能回滾的,並且部分的 DDL 語句會造成隱式的提交。
  • 在事務中可以通過定義 SAVEPOINT,指定回滾事務的一個部分,但是不能指定提交事務的一個部分。對於複雜的應用,可以定義多個不同的 SAVEPOINT,滿足不同的條件時,回滾不同的 SAVEPOINT。需要注意的是,如果定義了相同名字的 SAVEPOINT,則後面定義的 SAVEPOINT 會覆蓋之前的定義。對於不再需要使用的 SAVEPOINT,可以通過 RELEASE SAVEPOINT 命令刪除 SAVEPOINT,刪除後的 SAVEPOINT 不能再執行 ROLLBACK TO SAVEPOINT 命令。

3) 分散式事務

  • MySQL 從5.0.3開始支援分散式事務,當前分散式事務只支援 InnoDB 儲存引擎。一個分散式事務會涉及多個行動,這些行動本身是事務性的。所有行動都必須一起成功完成,或者一起被回滾。
  • 在 MySQL 中,使用分散式事務的應用程式設計一個或多個資源管理器和一個事務管理器。

   資源管理器(RM)用於提供通向事務資源的途徑。資料庫伺服器是一種資源管理器,該管理器必須可以提交或回滾由 RM 管理的事務。例如,多臺 MySQL 資料庫作為多臺資源管理器或者幾臺 MySQL 伺服器和幾臺 Oracle 伺服器作為資源管理器。

  事務管理器(TM)用於協調作為一個分散式事務一部分的事務。TM 與管理每個事務的 RMs 進行通訊。在一個分散式事務中,各個單個事務均是分散式事物的“分支事務”。分散式事務和各分支通過一種命名方法進行標識。

  • MySQL 執行 XA MySQL 時,MySQL 伺服器相當於一個用於管理分散式事務中的 XA 事務的資源管理器。與 MySQL 伺服器連線的客戶端相當於事務管理器。
  • 要執行一個分散式事務,必須知道這個分散式事務涉及了哪些資源管理器,並且把每個資源管理器的事務執行到事務可以被提交或回滾時。根據每個資源管理器報告的有關執行情況的內容,這些分支事務必須作為一個原子性操作全部提交或回滾。要管理一個分散式事務,必須要考慮任何元件或連線網路可能會出現的故障。
  • 用於執行分散式事務的過程使用兩階段進行提交,發生時間由分散式事務的各個分支需要進行的行動已經被執行之後。

  在第一階段,所有的分支被預備好。即他們被 TM 告知要準備提交。通常,這意味著用於管理分支的每個 RM 會記錄對於被穩定儲存的分支的行動。分支指示是否他們可以這麼做。這些結果被用於第二階段。

  在第二階段,TM 告知 RMs 是否要提交或回滾。如果在預備分支時,所有的分支指示他們能夠提交,則所有的分支被告知要提交。如果在預備時,有任何分支指示它將不能提交,則所有的分支被回滾。

    在有些情況下,一個分散式事務可能會使用一階段提交。例如,當一個事務管理器發現,一個分散式事務只由一個事務資源組成(即單一分支),則該資源可以被告知同時進行預備和提交。

  • 分散式事務(XA 事務)的語法

   啟動:

      XA {START|BEGIN} xid [JOIN|RESUME]

   XA START xid 用於啟動一個帶給定 xid 值的 XA 事務。每個 XA 事務必須有一個唯一的 xid 值,因此該值當前不能被其他的 XA 事務使用。xid 是一個 XA 事務識別符號,用來唯一標識一個分散式事務。xid 值有客戶端提供,或由 MySQL 伺服器生成。xid 值包含 1~3個部分:

      xid: gtrid[, bqual[, formatID]]

   gtrid是一個分散式事務識別符號,相同的分散式事務應該使用相同的 gtrid,這樣可以明確知道 XA 事務屬於哪個分散式事務。

   bqual 是一個分支限定符,預設值是空串。對於一個分散式事務中的每個分支事務,bqual 值必須是唯一的。

   formatID 是一個數字,用於標識由 gtrid 和 bqual 值使用的格式,預設值是1。

   使事務進入 PREPARE 狀態,也就是兩階段提交的第一個提交階段:

      XA END xid [SUSPEND [FOR MIGRATE]]

      XA PREPARE xid

   提交或者回滾具體的事務分支,也就是兩階段提交的第二個提交階段,分支事務被實際的提交或者回滾:

      XA COMMIT xid [ONE PHASE]

      XA ROLLBACK xid

   返回當前資料庫終於處於 PREPARE 狀態的分支事務的詳細資訊:

      XA RECOVER

  • 分散式的關鍵在於如何確保分散式事務的完整性,以及在某個分支出現問題時的故障解決。XA 的相關命令就是提供給應用如何在多個獨立的資料庫之間進行分散式事務的管理,包括啟動一個分散式事務、使事務進入準備階段以及事務的實際提交回滾操作等。
  • 雖然 MySQL 支援分散式事務,但是如果分支事務在達到 PREPARE 狀態時,資料庫異常重新啟動,伺服器重新啟動以後,可以繼續對分支事務進行提交或回滾操作,但是提交的事務沒有寫 binlog,存在一定的隱患,可能導致使用 binlog 恢復丟失部分資料。如果存在複製的資料庫,則有可能導致主從資料庫的資料不一致。
  • 使用 mysqlbinlog 檢視 binlog,可以確認最後提交的這個分支事務並沒有記錄到 binlog 中,因為複製和災難恢復都是依賴於 binlog的,所以 binlog 的確實會導致複製環境的不同步,以及使用 binlog 恢復丟失部分資料。