事務(wù)的實(shí)現(xiàn)機(jī)制與實(shí)際應(yīng)用:
- 事務(wù)概述
- 事務(wù)控制語(yǔ)句
- 事務(wù)隔離級(jí)別
- InnoDB鎖機(jī)制
- 事務(wù)概述
事務(wù)特性:
- 原子性(Atomicity): 事務(wù)中所有的操作視為一個(gè)原子單元,即對(duì)事務(wù)所進(jìn)行的數(shù)據(jù)修改等操作只能是完全提交或者完全回滾晴叨。
- 一致性(Consistency): 事務(wù)在完成時(shí)府适,必須使所有的數(shù)據(jù)從一種一致性狀態(tài)變更為另外一種一致性狀態(tài)担扑,所有的變更都必須應(yīng)用于事務(wù)的修改阐肤,以確保數(shù)據(jù)的完整性拓颓。
- 隔離性(Isolation):一個(gè)事務(wù)中的操作語(yǔ)句所做的修改必須與其他事務(wù)所做的修改相隔離。在進(jìn)行事務(wù)查看數(shù)據(jù)時(shí)关筒,數(shù)據(jù)所處的狀態(tài)溶握,要么是被另一并發(fā)事務(wù)修改之前的狀態(tài),要么是被另一并發(fā)事務(wù)修改之后的狀態(tài)蒸播,即當(dāng)前事務(wù)不會(huì)查看由另一個(gè)并發(fā)事務(wù)正在修改的數(shù)據(jù)睡榆。這種特性通過(guò)鎖機(jī)制實(shí)現(xiàn)。
- 持久性(Durability): 事務(wù)完成之后袍榆,所做的修改對(duì)數(shù)據(jù)的影響是永久的胀屿,即使系統(tǒng)重啟或者出現(xiàn)系統(tǒng)故障數(shù)據(jù)仍可以恢復(fù)。
(1) REDO日志
事務(wù)執(zhí)行時(shí)需要將執(zhí)行的事務(wù)日志寫(xiě)入到日志文件里包雀,對(duì)應(yīng)的文件為REDO日志宿崭。日志緩沖區(qū)的刷新方法或者時(shí)間間隔可以通過(guò)參數(shù)innodb_flush_log_at_trx_commit控制。
REDO日志對(duì)應(yīng)磁盤(pán)上的ib_logfileN文件馏艾,該文件默認(rèn)為5MB劳曹,建議設(shè)置為512MB以便容納較大的事務(wù)。其中ib_logfile0和ib_logfile1為REDO日志琅摩。
(2) UNDO日志
與REDO日志相反铁孵,UNDO日志主要用于事務(wù)異常時(shí)的數(shù)據(jù)回滾,具體內(nèi)容就是復(fù)制事務(wù)前的數(shù)據(jù)庫(kù)內(nèi)容到UNDO緩沖區(qū)房资,然后在合適的時(shí)間將內(nèi)容刷新到磁盤(pán)蜕劝。
- 事務(wù)控制語(yǔ)句
# 查看MySQL隔離級(jí)別
show variables like 'tx_isolation';
# 創(chuàng)建測(cè)試需要的表,注意存儲(chǔ)引擎為InnoDB
use test
# 創(chuàng)建表
create table test_1(
id int,
username varchar(20)
)engine=InnoDB;
# 插入語(yǔ)句
insert into test_1
values(1,'petter'),
(2,'bob'),(3,'allen'),(4,'aron');
# 查詢數(shù)據(jù)
select * from test_1;
# 開(kāi)啟一個(gè)事務(wù)
begin;
# 更新一條記錄
update test_1 set username='test' where id=1;
OK, 1 row affected (0.00 sec)
# 提交事務(wù)
commit;
# 查詢數(shù)據(jù)
select * from test_1;
# 開(kāi)啟另一個(gè)事務(wù)
begin;
# 更新數(shù)據(jù)
update test_1 set username='petter' where id=1;
# 查詢數(shù)據(jù)
select*from test_1;
# 回滾事務(wù)
rollback;
# 查詢數(shù)據(jù)
select * from test_1;
- 事務(wù)隔離級(jí)別
# 未提交讀
set global transaction isolation level read uncommitted;
# 提交讀
set global transaction isolation level read committed;
# 可重復(fù)讀
set global transaction isolation level repeatable read;
# 可串行讀
set global transaction isolation level serializable;
(1)READ-UNCOMMITTED(讀取未提交內(nèi)容)
在該隔離級(jí)別轰异,所有事務(wù)都可以看到其他未提交事務(wù)的執(zhí)行結(jié)果岖沛。讀取未提交的數(shù)據(jù)被稱(chēng)為臟讀(Dirty Read);
(2)READ-COMMITTED(讀取提交內(nèi)容)
這是大多數(shù)數(shù)據(jù)庫(kù)系統(tǒng)的默認(rèn)隔離級(jí)別,但不是MYSQL的默認(rèn)隔離級(jí)別搭独。滿足了隔離的簡(jiǎn)單定義: 一個(gè)事務(wù)從開(kāi)始到提交前所做的任何改變都是不可見(jiàn)的婴削,事務(wù)只能看見(jiàn)已經(jīng)提交事務(wù)所做的改變。這種隔離級(jí)別也支持所謂的不可重復(fù)讀(Nonrepeatable Read)牙肝,因?yàn)橥皇聞?wù)的其他實(shí)例在該實(shí)例處理期間可能會(huì)有新的數(shù)據(jù)提交導(dǎo)致數(shù)據(jù)改變唉俗,所以同一查詢可能返回不同結(jié)果嗤朴,此級(jí)別導(dǎo)致不可重復(fù)讀。
(3)REPEATABLE-READ(可重讀)
這是MYSQL默認(rèn)的事務(wù)隔離級(jí)別虫溜,能確保同一事務(wù)的多個(gè)實(shí)例在并發(fā)讀取數(shù)據(jù)時(shí)雹姊,會(huì)看到同樣的數(shù)據(jù)行。理論上會(huì)導(dǎo)致幻讀(Phantom Read)衡楞。
(4) Serializable(可串行化)
這是最高的隔離級(jí)別吱雏,通過(guò)強(qiáng)制事務(wù)排序,是之不可能相互沖突瘾境,從而解決幻讀問(wèn)題歧杏。簡(jiǎn)言之,就是在每個(gè)讀的數(shù)據(jù)行上加上共享鎖實(shí)現(xiàn)寄雀。這個(gè)級(jí)別得滤,可能會(huì)導(dǎo)致大量的超時(shí)現(xiàn)象和所競(jìng)爭(zhēng),一般不推薦使用盒犹。
- InnoDB鎖機(jī)制
(1) 鎖的類(lèi)型(共享鎖/排他鎖/意向鎖)
- 共享鎖
共享鎖代號(hào)是S懂更,是Share的縮寫(xiě),共享鎖的所力度是行或者元組(多個(gè)行)急膀。一個(gè)事務(wù)獲取了共享鎖之后沮协,可以對(duì)鎖定范圍內(nèi)的數(shù)據(jù)執(zhí)行讀操作。 - 排他鎖
排他鎖的代號(hào)是X卓嫂,是eXclusive的縮寫(xiě)慷暂,排他鎖的粒度與共享鎖相同,也是行或者元組晨雳。一個(gè)事務(wù)獲取了排他鎖之后行瑞,可以對(duì)鎖定范圍內(nèi)的數(shù)據(jù)執(zhí)行寫(xiě)操作。 - 意向鎖
意向鎖是一種表鎖餐禁,鎖定的粒度是整張表血久,分為意向共享鎖(IS)和意向排他鎖(IX)兩類(lèi)。意向共享鎖表示一個(gè)事務(wù)有意對(duì)數(shù)據(jù)上共享鎖或者排他鎖帮非⊙跬拢“有意”表示事務(wù)想執(zhí)行操作但還沒(méi)有真正執(zhí)行。
(2) 鎖粒度
鎖的粒度主要分為表鎖和行鎖末盔。
表鎖管理鎖的開(kāi)銷(xiāo)最小筑舅,同時(shí)允許的并發(fā)量也是最小的鎖機(jī)制。行鎖可以支持最大的并發(fā)陨舱。