在進入交易Transactions之前,必須先理解ACID的概念
1.Atomicity,原子性,所有的SQL語句都是不可分割的個體,只要其中一句失敗,交易就會被復原
2.Consistency,一致性,資料庫始終保持一致性,舉例來說不會出現交易後,發現某張訂單少了價格或是數量
3.Isolation,隔離性,交易彼此之間相互隔離,受影響的行在交易發生會上鎖,其他交易必須等其完成才能執行
4.Durability,持久性,一旦交易被提交(COMMIT),就算電腦當機、或是系統崩潰都不會影響結果
看完以上四點,大概可以理解交易的基本性質,只會出現兩種結果,成功提交或是失敗回滾(ROLLBACK),交易的應用非常多,以下舉2個常見的例子
1.銀行轉帳,轉帳一定分成至少兩個步驟,首先是轉帳者的帳戶扣款,其次是被轉帳者的帳戶進帳,其中只要一個步驟失敗,整個交易就會回復到還沒發生過的狀態
2.商品訂單,當消費者點選確定結帳後,大多數的情況都會成立一筆訂單,基於資料庫的正規化,訂單明細會放在另外一張表,所以同樣是必須先插入一行訂單再插入訂單明細,假設不使用交易的寫法,就會發生悲劇
小明在網路上買了10隻筆,但是負責電商後台的工程師因為沒喝咖啡導致想睡覺,忘記使用交易就直接插入資料庫,好巧不巧伺服器又突然當機,就會發生以下的悲劇
為了方便舉例,SQL使用分級插入裡的範例
INSERT INTO orders (order_id, name, order_date,comments) -- 插入一筆剛成立的訂單
VALUES (default, '小明','2019-01-01', 'good');
-- 伺服器突然掛了,以下語句無法執行
INSERT INTO order_details -- 消失的訂單明細
VALUES
(default, 1, 10, 10),
(default, 2, 10, 10),
(default, 3, 10, 10);
結果就會變成有一筆訂單對應不到訂單明細,其實這是蠻嚴重的問題,不過使用交易也不代表從此萬無一失,可能因為錯誤的使用導致死鎖的發生,過度的使用也可能導致效能下降的問題。
START TRANSACTION;
INSERT INTO orders (order_id, name, order_date,comments)
VALUES (default, '小明','2019-01-01', 'good');
INSERT INTO order_details
VALUES
(default, 1, 10, 10),
(default, 2, 10, 10),
(default, 3, 10, 10);
COMMIT;
Day13-MySQL的併發(Concurrency)