目錄
一、事務
事務有ACDI原則
1.原子性(Atomicy)
要麼都成功,要麼都失敗
2. 一致性(Consistency)
事務前後的數據保持一致
3.持久性(Durability) – 事務提交
事務一旦提交不可逆
4.隔離性 (Isolation)
多個人,同時給張三轉錢的時候,每一筆轉賬開啓一個事務,多個事務相互隔離就是隔離性
二、隔離性產生的數據問題
多個用戶都在操作數據產生的數據問題。
1.髒讀 :一個事務讀取了了另一個事務沒有提交的 數據
1.比如張三和李四同時區銀行取相同賬號的錢,此時賬戶上有1000,李四,取錢1000,數據還沒有提交成功
2.張三以迅雷不及掩耳之勢迅速取錢 1000,此時因爲賬戶的數據還沒有來得及修改,於是,張三查詢餘額的時候還是1000.
2.不可重複讀:多次數據讀取的結果不同 (這個不一定是錯誤)
1.你查看 QQ 的信息,第一次刷新,沒有人給你發信息,第二次刷新,出現了一條信息,2次查詢的結果不一致,因爲第一次刷新的對方還沒有提交成功,就是不可重複讀
3.虛讀(幻讀):在一個事務內讀取到了別人插入的數據,導致前後不一致。
和不可重複讀類似,第一次查詢餘額的時候,是1000 元,然後別人充值了1000 元,你第二次查詢的時候就是 2000 元了,
三、事務4個隔離級別
1.四個隔離級別的瞭解
設置級別 | 髒讀 | 不可重複讀 | 幻讀 |
---|---|---|---|
可讀未提交(read-uncommitted) | 會 | 會 | 會 |
只讀提交(read-committed) | 會 | 會 | |
可重複讀(repeatable-read) | 會 | ||
可序列化(serializable) |
可見,可序列化 serializable,最安全但是速度最慢。
值得一提的是:大多數數據庫默認 read-committted 比如SQLServer 和Oracle,MySQL是更高級的 repeatable-read.
2.四個隔離級別詳解:
參考博客 https://blog.csdn.net/qq_33290787/article/details/51924963
2.1.可讀未提交 (read-uncommitted)
(1)意義:顧名思義,讀取的修改了(update)沒有提交(submit)的數據
(2)問題:會產生所有的隔離性數據問題
(3)舉例:張三,工資1萬元/月,但是,老闆給他發工資的時候不小心多輸入了一個0,10萬/月,此時update的SQL以及執行了,但是還沒有submit,張三早上查看自己的工資看到欣喜若狂,但是老闆發現自己輸入了一個0,連忙回滾(rollback),張三的工資又回到了設置之前,毫不知情的張三卻還樂呵呵的清空着他的購物車。這就是髒讀
2.2 只讀提交(read-committed)
(1)意義:就是隻能讀取提交後的數據,
(2)問題:解決髒讀的問題,但是其他問題依舊存在。
(3)舉例:
- 1.解決髒讀問題:張三,工資1萬元/月,但是,老闆給他發工資的時候不小心多輸入了一個0,10萬/月,此時update的SQL以及執行了,但是還沒有submit,張三早上查看自己的工資還是以前的工資,應爲老闆還沒提交submit
- 2.不可重複讀取的問題:張三和朋友聚餐,“服務員結賬!”張三招了招手,服務員唯唯諾諾過來,張三掏出手機看了看自己的餘額,1000元,“掃碼”,服務員趕緊立馬拿出了收款碼,張三對準二維碼正掃描着,(同時張三的女朋友用張三的銀行卡清空了自己1000元的的購物車,並付款支付成功)張三手機叮一聲,掃碼成功,一個圈圈轉啊轉,最後彈出一條提示,“您的餘額不足”,張三當時心態爆炸。這就是不可重複讀
2.3. 可重複讀(repeatable-read)
(1)意義:可以重複讀取的數據
(2)問題:在read-committed的基礎上解決update,更新數據產生的不可重複讀的問題,但是還有插入insert導致的幻讀的問題。
(3)舉例:
- 1.解決不可重複讀的問題: 張三買單時(事務開啓,不允許其他事務驚醒update操作),同時張三的女朋友用張三的銀行卡清空自己1000元的的購物車,並付款**,無法進行update操作,付款失敗**。)張三消費成功。
- 2.幻讀的問題:張三女友購物消費1000,然後她去查看自己的消費記錄(妻子事務開啓,掃描全表)正在查找的時候,張三消費1000元請朋友喫飯,(張三提交消費數據insert)此時妻子打印消費結果的時候發現多了一個1000元的消費,一共消費了2000元,似乎產生的幻覺,這就是幻讀,幻讀其實並不一定是錯誤。
2.4.序列化Serializable
(1)意義:參考幻讀的問題
(2)問題:解決所有數據讀取問題,但是因爲速度太低,一般不採用
(3)例子:參考幻讀的問題。
3.如何設置事務的隔離級別?
3,1 全局修改
在mysql.ini 配置文件最後加上
#可選的參數有: read-uncommitted ,read-committed ,repeatable-read,serializable
[mysqld]
transaction-isolation = REPEATABLE-READ
3.2 對當前session修改
登錄mysql之後,輸入
set session transaction isolation level read uncommitted;
四、事務的案例模擬
1.建表
1.數據庫 事務銀行 tansactionBank
CREATE DATABASE IF NOT EXISTS `transactionBank`CHARACTER SET utf8 COLLATE utf8_general_ci;
2.表 事務銀行 tansactionBank01
CREATE TABLE IF NOT EXISTS `tansactionBank01`(
`id` INT NOT NULL AUTO_INCREMENT COMMENT "賬號",
`name` VARCHAR(30) NOT NULL COMMENT "名稱",
`money` DECIMAL(9,2) NOT NULL DEFAULT 0 COMMENT "賬戶餘額00.00格式默認爲0",
PRIMARY KEY (`id`)
)ENGINE = INNODB DEFAULT CHARSET=utf8
3.插入數據:
INSERT INTO `tansactionbank01`
(`name`,`money`)
VALUES
("張三",0),
("李四",1000);
最終效果:
2. 瞭解事務的基本操作
操作 | 作用 | 解釋 |
---|---|---|
set autocommit = 0; | 關閉自動提交,mysql默認啓動自動提交 | 使用手動事務之前關閉自動提交事務 |
set autocommit = 1; | 啓動功自動提交 | 使用手動提交事務之後開啓自動提交事務 |
start transaction; | 開啓一個(組)事務 | |
commit; | 提交事務 | 持久性,提交之後不能回滾了 |
rollback; | 回滾事務 | 回到最初的起點(有存檔的辦法可回到存檔點但是不常用瞭解即可.) |
3. 事務實例:使用事務李四給張三轉賬 500元
-- 1. 關閉自動提交,方便手動提交
SET autocommit = 0;
-- 2.開啓一個(組)新的事務
START TRANSACTION;
-- 3.進行事務轉賬操作
UPDATE `tansactionbank01` SET
`money` = `money`- 500
WHERE `name` = "李四";
UPDATE `tansactionbank01` SET
`money` = `money`+ 500
WHERE `name` = "張三";
-- 4. 回滾
ROLLBACK;
-- 4.2 提交
COMMIT;
-- 4.3 提交後再回滾 (數據已經更改持久性,不能回滾成功)
COMMIT;
ROLLBACK;
-- 5.把自動提交恢復爲默認.
SET autocommit = 1;