官术网_书友最值得收藏!

MySQL中的事務

存儲引擎是驅動如何從硬盤中存儲和檢索數據的軟件。雖然MySQL傳統上提供了許多支持事務的存儲引擎,但InnoDB現在已經成為金標準,是推薦使用的引擎。這里描述的事務原語將基于InnoDB引擎中的事務。

理解AUTOCOMMIT

默認情況下,單個INSERT、UPDATE或DELETE語句會被隱式包裝在一個事務中并在執行成功后立即提交,這稱為自動提交(AUTOCOMMIT)模式。通過禁用此模式,可以在事務中執行一系列語句,并在結束時執行COMMIT提交事務或ROLLBACK回滾事務。

在當前連接中,可以使用SET命令設置AUTOCOMMIT變量來啟用或禁用自動提交模式。啟用可以設置為1或者ON,禁用可以設置為0或者OFF。如果設置了AUTOCOMMIT=0,則當前連接總是會處于某個事務中,直到發出COMMIT或者ROLLBACK,然后MySQL會立即啟動一個新的事務。此外,當啟用AUTOCOMMIT時,也可以使用關鍵字BEGIN或者START TRANSACTION來開始一個多語句的事務。修改AUTOCOMMIT的值對非事務型的表不會有任何影響,這些表沒有COMMIT或者ROLLBACK的概念。

還有一些命令,當在活動的事務中發出時,會導致MySQL在事務的所有語句執行完畢前提交當前事務。這些通常是進行重大更改的DDL命令,如ALTER TABLE,但LOCK TABLES和其他一些語句也具有同樣的效果。有關會導致自動提交事務的完整命令列表,請查看對應版本的官方文檔。

MySQL可以通過執行SET TRANSACTION ISOLATION LEVEL命令來設置隔離級別。新的隔離級別會在下一個事務開始的時候生效。可以在配置文件中設置整個服務器的隔離級別,也可以只改變當前會話的隔離級別:

建議最好在服務器級別設置最常用的隔離,并且只在顯式情況下修改。MySQL可以識別所有4個ANSI標準的隔離級別,InnoDB也支持這些隔離級別。

在事務中混合使用存儲引擎

MySQL不在服務器層管理事務,事務是由下層的存儲引擎實現的。所以在同一個事務中,混合使用多種存儲引擎是不可靠的。

假設在事務中混合使用事務表和非事務表(例如,InnoDB和MyISAM表),如果一切順利,事務將正常工作。如果需要回滾,則無法撤銷對非事務表的更改。這會使數據庫處于不一致的狀態,可能難以恢復,并使整個事務問題變得毫無意義。所以,為每張表選擇合適的存儲引擎,并不惜一切代價避免在應用中混合使用存儲引擎是非常重要的。

在非事務表中執行事務相關操作的時候,MySQL通常不會發出提醒,也不會報錯。有時候只有回滾的時候才會發出一個警告:某些非事務表中的變更無法回滾。但在大多數情況下,對非事務表的操作都不會有提示。

最好不要在應用程序中混合使用存儲引擎。失敗的事務可能導致不一致的結果,因為某些部分可以回滾,而其他部分不能回滾。

隱式鎖定和顯式鎖定

InnoDB使用兩階段鎖定協議(two-phase locking protocol)。在事務執行期間,隨時都可以獲取鎖,但鎖只有在提交或回滾后才會釋放,并且所有的鎖會同時釋放。前面描述的鎖定機制都是隱式的。InnoDB會根據隔離級別自動處理鎖。

另外,InnoDB還支持通過特定的語句進行顯式鎖定,這些語句不屬于SQL規范:[9][10]

MySQL還支持LOCK TABLES和UNLOCK TABLES命令,這些命令在服務器級別而不在存儲引擎中實現。如果需要事務,應該使用支持事務的存儲引擎。因為InnoDB支持行級鎖,所以沒必要使用LOCK TABLES。

LOCK TABLES命令和事務之間的交互非常復雜,并且在一些服務器版本中存在意想不到的行為。因此,本書建議,除了在禁用AUTOCOMMIT的事務中可以使用之外,其他任何時候都不要顯式地執行LOCK TABLES,不管使用的是什么存儲引擎。

主站蜘蛛池模板: 华容县| 沁源县| 桐梓县| 弋阳县| 龙南县| 阿拉善左旗| 隆尧县| 丰原市| 波密县| 紫阳县| 托里县| 明溪县| 东宁县| 灵石县| 民勤县| 长治市| 泰兴市| 瑞丽市| 麦盖提县| 都匀市| 宿松县| 陇西县| 顺昌县| 彩票| 聂拉木县| 安陆市| 宣威市| 台湾省| 定西市| 柳河县| 留坝县| 奉化市| 平顺县| 秀山| 昌图县| 唐河县| 张掖市| 衡东县| 吐鲁番市| 海口市| 潜山县|