SQLyog基本操作(八)-事務
6 事務
定義:資料庫事務是構成單一邏輯工作單元的操作集合。
一個典型的資料庫事務如下:
BEGIN TRANSACTION //事務開始
SQL1
SQL2
COMMIT/ROLLBACK //事務提交或回滾
可以理解為:將一組SQL放在一個批次中去執行
關於事務的定義有幾點需要解釋:
-
資料庫事務可以包含一個或多個數據庫操作,但這些操作構成一個邏輯上的整體。
-
構成邏輯整體的這些資料庫操作,要麼全部執行成功,要麼全部不執行。
-
構成事務的所有操作,要麼全都對資料庫產生影響,要麼全都不產生影響,即不管事務是否執行成功,資料庫總能保持一致性狀態。
-
事務的四個原則:ACID(原子性、一致性、隔離性、永續性)
參考部落格
-
原子性(Atomicity)
原子性是指事務是一個不可分割的工作單位,事務中的操作,要多都發生,要麼都不發生;要麼都成功,要麼都失敗。
針對同一個事務而言
舉例:銀行轉賬
這個過程包含兩個步驟:
A:800 - 200 = 600 轉出200 B:200 + 200 = 400 轉入200
原子性表示,這兩個步驟要麼一起成功,要麼一起失敗,不能只發生其中一個動作。
-
一致性(Consistency)
一致性是指事務前後的資料完整性要保持一致(最終一致性、過程一致性)。
針對一個事務操作前與操作後的狀態一致。
舉例:銀行轉賬
操作前A:800,B:200 操作後A:600,B:400
一致性表示事務完成後,符合邏輯運算(前後過程、最終的總錢數也都保持一致:1000)
-
永續性(Durability)
永續性是指一個事務一旦被提交,它對資料庫中資料的改變就是永久性的(不可逆,被持久化到資料庫中),接下來即使資料庫發生故障也不應該對其產生任何影響。
表示事務結束後的資料不隨著外界原因導致資料丟失。
舉例:銀行轉賬
操作前A:800,B:200 操作後A:600,B:400
-
如果在操作前(即事務還沒有被提交)伺服器宕機或者斷電,那麼重啟資料庫以後,資料狀態應該為 A:800,B:200
-
如果在操作後(即事務已經被提交)伺服器宕機或者斷電,那麼重啟資料庫以後,資料狀態應該為 A:600,B:400
-
隔離性(Isolation)
事務的隔離性是指多個使用者併發訪問資料庫時,資料庫為每一個使用者開啟的事務,不能被其他事務的操作資料所幹擾,多個併發事務之間要相互隔離。
針對多個使用者同時操作,主要是排除其他事務對本次事務的影響。
舉例:銀行轉賬
事務一:A向B轉賬200
事務二:C向B轉賬100
兩個事務同時進行,其中一個事務讀取到另外一個事務還沒有提交的資料,執行步驟如圖所示:
隔離性用於解決以上問題。
隔離所導致的一些問題:
-
髒讀
指一個事物讀取了另外一個事務未提交的資料。
舉例:
-
不可重複讀
在一個事務內讀取表中的某一行資料,多次讀取結果不同(這不一定是錯誤,只是某些場合不對)。
舉例:頁面統計查詢值
生成報表的時候,B有人轉賬進來300(B事務已經提交)
-
虛讀(幻讀)
是指在一個事務內讀取到了別的事務插入的資料,導致前後讀取的不一樣,一般是行影響。
舉例:多了一行
事務流程:
-- mysql是預設開啟事務自動提交的
SET autocommit=0 /* 關閉事務自動提交 */
SET autocommit=1 /* 開啟事務自動提交 */
-- 手動處理事務,要先關閉自動提交
SET autocommit=0
-- 標記一個事務的開始,從這個之後的sql都在同一個事務內
START TRANSACTION
-- 一組事務
INSERT xx
INSERT xx
-- 提交:成功-->持久化,就不能再回滾了
COMMIT
-- 回滾:失敗-->回滾(回到原來的樣子),未提交時,可以回滾
ROLLBACK
-- 事務結束,開啟自動提交
SET autocommit=1
-- 瞭解
SAVEPOINT 儲存點名 -- 設定一個事務的儲存點
ROLLBACK TO SAVEPOINT 儲存點名 -- 回滾到儲存點
RELEASE SAVEPOINT 儲存點名 -- 撤銷儲存點
舉例:轉賬業務
-- 事務案例:轉賬業務
-- 建立資料庫
CREATE DATABASE `bank` CHARACTER SET utf8 COLLATE utf8_general_ci
-- 使用資料庫
USE `bank`
-- 建立表
CREATE TABLE `account`(
`id` INT(4) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(20) NOT NULL,
`money` DECIMAL(9,2) NOT NULL,
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
-- 插入資料
INSERT INTO `account`(`name`,`money`) VALUES('A',10000.00),('B',20000.00)
-- 模擬轉賬:事務
SET autocommit=0; -- 關閉自動提交
START TRANSACTION -- 開始一個事務(一組事務)
-- 具體事務
UPDATE `account` SET `money`=`money`-500 WHERE `name`='A' -- A減500
UPDATE `account` SET `money`=`money`+500 WHERE `name`='B' -- B加500
COMMIT -- 成功提交事務,資料就被持久化了
ROLLBACK -- 失敗回滾事務
SET autocommit=1; -- 事務結束,開啟自動提交