數據庫的事務 - 初遇事務一(極客時間)

初遇事務

在MySQL5.5以前, 默認的存儲引擎是MyISAM, 在5.5版本以後默認存儲引擎是InnoDB, 而這兩個存儲引擎的最大區別就在於InnoDB是支持事務的, 這也是InnoDB取代MyISAM的重要緣由. 什麼是事務呢? 事務的英文是transaction, 也就是進行一次處理的基本單元, 要麼徹底執行, 要麼全都不執行.數據庫

事務的特性: ACID

深刻理解事務, 就須要知道事務的四個特性, 那就是ACID:編程

  1. A, 也就會說原子性(Aomicity). 原子的概念就是不可分割, 能夠理解爲組成物質的基本單元, 也就是數據處理操做的基本單位.
  2. C, 就是一致性(Consistency), 一致性指的是數據庫在進行事務操做後, 會有原來的一致狀態, 編程另外一種一致狀態. 也就是事務提交或回滾後, 數據庫的完成性約束不能破壞.
  3. I, 就是隔離性(Isolocation), 指的是每一個事務都是彼此獨立的, 不會受到其餘事務的執行影響. 簡單說就是一個事務在提交以前, 對其餘事務都是不可見的.
  4. D, 就是持久性(Durability), 事務提交以後對數據的修改是持久性的, 及時在系統出故障的狀況下(崩潰或存儲介質發生故障), 數據的修改依然是有效地. 由於當事務完成以後, 數據庫的日誌就會被更新, 這個經過日誌, 可讓系統恢復到最後一次成功的更新狀態.

這四個特性中, 原子性是基礎, 隔離性是手段, 一致性是約束條件, 持久性是目的. 原子性和隔離性好理解, 至於一致性相對難, 筆者開始老是不知道這個一致性所說的狀態是什麼意思, 直到如今看了這個文檔, 才發現.服務器

一致性自己是由具體的業務定義的, 任何寫入數據庫中的數據都須要知足咱們事先定義的約束規則, 到這裏就能夠理解一致性具體的含義了, 一致性其實說的是不違反約束規則, 好比主鍵約束, 惟一約束, 不爲NULL約束等等.日誌

另外一個持久性, 持久性是經過事務日誌來保證的. 日誌包括了回滾日誌和重作日誌. 經過事務對數據進行修改的時候, 首先會將數據庫的變化信息記錄到重作日誌中, 而後再對數據庫中對應的行進行修改, 這樣作的好處是, 即便數據庫崩潰, 數據庫重啓後也能找到沒有更新到數據庫系統中的重作日誌, 從新執行, 從而使事務具備持久性.code

事務的控制

Oracle是支持事務的, 而在MySQL中, 須要選擇合適的存儲引擎才能夠支持事務, 使用MySQL, 可使用SHOW ENGINES來查看當前MySQL支持的存儲引擎, 以及該引擎是否支持事務.blog

事務經常使用的控制語句:事務

  1. START TRANSACTION或者BEGIN, 做用是顯式開啓一個事務.
  2. COMMIT: 提交事務, 提交事務後, 對數據庫的修改是永久性的
  3. ROLLBACK或者ROLLBACK TO [SAVEPOINT], 回滾事務, 意思是撤銷正在進行的全部沒有提交的修改, 或者將事務回滾到某個保存點.
  4. SAVEPOINT: 在事務中建立保存點, 方便後續針對保存點進行回滾, 一個事務中能夠存在多個保存點.
  5. RELEASE SAVEPOINT: 刪除某個保存點
  6. SET TRANSACTION, 設置事務的隔離級別.

使用事務有兩種方式, 一種是隱式事務, 一種是顯示事務. 隱式事務其實就是自動提交. Oracle默認不自動提交, 須要手寫COMMIT命令, 而MySQL默認自動提交, 可使用MySQL的命令來配置參數關閉自動提交:set autocommit = 0;是關閉自動提交, set autocommit = 1;是開啓自動提交.ci

MySQL的默認狀態下:文檔

CREATE TABLE test(name varchar(255), PRIMARY KEY (name)) ENGINE=InnoDB;
BEGIN;
INSERT INTO test SELECT '關羽';
COMMIT;
BEGIN;
INSERT INTO test SELECT '張飛';
INSERT INTO test SELECT '張飛';
ROLLBACK;
SELECT * FROM test;

如今執行完的狀況下, 數據庫中默認保存了一條.

CREATE TABLE test(name varchar(255), PRIMARY KEY (name)) ENGINE=InnoDB;
BEGIN;
INSERT INTO test SELECT '關羽';
COMMIT;
INSERT INTO test SELECT '張飛';
INSERT INTO test SELECT '張飛';
ROLLBACK;
SELECT * FROM test;

如今數據庫中應該是兩條記錄, 由於默認會隱式提交, 也就是在執行第一個INSERT INTO test SELECT '張飛';的時候, 執行完成就會提交, 只有在執行第二個的時候會產生主鍵衝突而回滾.

CREATE TABLE test(name varchar(255), PRIMARY KEY (name)) ENGINE=InnoDB;
SET @@completion_type = 1;
BEGIN;
INSERT INTO test SELECT '關羽';
COMMIT;
INSERT INTO test SELECT '張飛';
INSERT INTO test SELECT '張飛';
ROLLBACK;
SELECT * FROM test;

結果是一條數據, 很明顯, 緣由是SET @@completion_type = 1;, 這個參數有3種可能:it

  1. completion=0, 這是默認狀況, 也就是執行COMMIT會提交事務, 執行下一個事務前, 須要使用START TRANSACTION或者BEGIN來開啓.
  2. completion=1, 這種狀況下, 提交事務後, 至關於執行了COMMIT AND CHAIN, 也就是開啓一個鏈式事務, 即當咱們提交事務以後會開啓一個相同隔離級別的事務.
  3. completion=2, 這種狀況下COMMIT=COMMIT AND RELEASE, 也就是當提交以後, 會自動與服務器斷開鏈接.

這裏使用了completion=1, 就是提交以後, 至關於在下一行寫了START TRANSACTION 或 BEGIN, 這是插入兩次張飛會被認爲是在同一個事務以內的操做, 因此回滾以後, 數據庫中就只有一條關羽的數據.

這個是事務的基本認識, 固然事務的隔離級別也很重要, 下一個隨筆說.

相關文章
相關標籤/搜索