目錄
1 事務的基本概念
如果一個包含多個步驟的業務操作,被事務管理,那麼這些操作要麼同時成功,要麼同時失敗。如下A給B轉錢的例子很形象的說明了事務的概念:
1.1 事務的操作
- 開啓事務:start transaction;
- 回滾:rollback;
- 提交:commit;
【舉例】:還是用這個A給B轉賬的例子,在SQLyog中進行模擬開啓事務、回滾、提交
-- 創建表
CREATE TABLE account (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10),
balance DOUBLE
);
-- 添加數據
INSERT INTO account (NAME, balance) VALUES ('zhangsan', 1000), ('lisi', 1000);
UPDATE account SET balance = 1000;
SELECT * FROM account;
-- 0. 開啓事務
START TRANSACTION;
-- 1. 張三賬戶 -500
UPDATE account SET balance = balance - 500 WHERE NAME = 'zhangsan';
-- 2. 李四賬戶 +500
-- 出錯了...
UPDATE account SET balance = balance + 500 WHERE NAME = 'lisi';
-- 發現執行沒有問題,提交事務
COMMIT;
-- 發現出問題了,回滾事務
ROLLBACK;
1)在A窗口中先開啓事務,然後執行張三賬戶-500,-》出錯了-》李四賬戶+500,此時查詢A窗口數據,張三確實-500,但李四還是100;在B窗口中查詢數據,張三和李四都是1000,沒發生變化;說明A窗口中開啓事務起了作用,且A中查詢的數據也只是暫時的。
2)發現錯誤後,執行回滾操作,再次在窗口A和B中查詢,數據都是1000,回滾操作成功。
3)在A窗口中先開啓事務,然後執行張三賬戶-500-》李四賬戶+500,此時查詢A窗口數據,張三確實-500,李四+500;在B窗口中查詢數據,張三和李四都是1000,沒發生變化;因在A窗口中的操作都OK,執行提交事務,再次在窗口A和B中查詢,數據都發生正確變化,事務提交成功。
1.2 MySQL數據庫的事務提交
1)事務提交的兩種方式
- 自動提交:MySQL數據庫默認是自動提交的,一條DML(增刪改語句)會自動提交一次事務;
- 手動提交:需要先開啓事務(START TRANSACTION),再提交(COMMIT);
Oracle數據庫默認是手動提交的;
2)修改事務的默認提交方式
- 查看默認提交方式:SELECT @@autocommit; -- 1代表自動提交,0代表手動提交
- 修改默認提交方式:SET @@autocommit = 0; -- 1代表自動提交,0代表手動提交
實際上手動控制事務的開啓與提交,可以大幅度提高數據插入的效率,在進行數據批量插入操作時可以手動控制事務。
2 事務的四大特徵
1)原子性:是不可分割的最小操作單位,要麼同時成功,要麼同時失敗;
2)持久性:事務一旦提交或回滾,數據表的數據將被持久化的保存;
3)隔離性:多個事務之間相互獨立;
4)一致性:表示事務操作前後,數據總量不變。
3 事務的隔離級別
多個事務之間是隔離的,相互獨立的,但是如果多個事務操作同一批數據,則會引發一些問題,設置不同的隔離級別,就可以解決這些問題。
3.1 存在的問題
1)髒讀:一個事務讀取到另一個事務中沒有提交的數據;
【舉例】:A給B發1000塊錢,手一抖打了10000,這個錢已經打到B的戶口,但是事務還沒有提交,這時B查下卡,發現多了9000,興奮壞了,但是A及時發現,馬上回滾差點提交的事務,將數字改回1000再提交。
2)不可重複讀(虛讀):在同一個事務中兩次讀取到的數據不一樣;
【舉例】:A拿着卡去購物,卡里有1000塊錢,當A買單時(事務開啓),收費系統事先檢測到他的卡里有1000,就在這個時候,A的妻子要把錢全部拿出來買首飾,並提交。當收費系統準備扣款時,再檢測卡里的金額,發現已經沒錢了(第二次檢測金額當然要等待A的妻子轉出金額事務提交完),A就會很鬱悶,錢哪去了。。。
3)幻讀:一個事務操作(DML)數據表中所有的記錄,另一個事務添加了一條數據,則第一個事務查詢不到自己的修改;
【舉例】:A去消費,花了1千元,A的妻子去查看他今天的消費記錄(全表掃描FTS,妻子事務開啓),看到確實是花了1千元,就在這時,A又花了1千元買了一個機械鍵盤,即新增INSERT了一條消費記錄,並提交。當妻子打印消費記錄清單時(妻子事務提交),發現花了2千元,似乎出現了幻覺,這就是幻讀。
3.2 隔離級別
1)read uncommitted:讀未提交
【會產生的問題】:髒讀、不可重複讀、幻讀
2)read committed:讀已提交(Oracle默認)
【會產生的問題】:不可重複讀、幻讀
3)repeatable read:可重複讀(MySQL默認)
【會產生的問題】:幻讀
4)serializable:串行化
【會產生的問題】:可以解決所有問題
【注意】:隔離級別從小到大,安全性越來越高,但是效率越來越低。但是一般情況下不會修改數據庫默認的隔離級別,只有在極特殊情況下才會做出修改已解決一些特殊問題。
數據庫查詢隔離級別:select @@tx_isolation;
數據庫設置隔離級別:set global transaction isolation level 級別字符串;
———————————————————————————————————————
本文爲博主原創文章,轉載請註明出處!
若本文對您有些許幫助,輕擡您發財的小手,關注/評論/點贊/收藏,就是對我最大的支持!
祝君升職加薪,鵬程萬里!