一衬廷、事務(wù)定義
Transaction
事務(wù):一個(gè)最小的不可再分的工作單元鲤氢;通常一個(gè)事務(wù)對(duì)應(yīng)一個(gè)完整的業(yè)務(wù)(例如銀行賬戶轉(zhuǎn)賬業(yè)務(wù)搀擂,該業(yè)務(wù)就是一個(gè)最小的工作單元)
一個(gè)完整的業(yè)務(wù)需要批量的DML(insert、update卷玉、delete)語句共同聯(lián)合完成
事務(wù)只和DML語句有關(guān)哨颂,或者說DML語句才有事務(wù)。這個(gè)和業(yè)務(wù)邏輯有關(guān)相种,業(yè)務(wù)邏輯不同威恼,DML語句的個(gè)數(shù)不同
二、轉(zhuǎn)賬操作理解事務(wù)
關(guān)于銀行賬戶轉(zhuǎn)賬操作蚂子,賬戶轉(zhuǎn)賬是一個(gè)完整的業(yè)務(wù)沃测,最小的單元,不可再分————————也就是說銀行賬戶轉(zhuǎn)賬是一個(gè)事務(wù)
以下是銀行賬戶表t_act(賬號(hào)食茎、余額)蒂破,進(jìn)行轉(zhuǎn)賬操作
actno balance
1 500
2 100
轉(zhuǎn)賬操作
update t_act set balance=400 where actno=1;
update t_act set balance=200 where actno=2;
以上兩臺(tái)DML語句必須同時(shí)成功或者同時(shí)失敗。最小單元不可再分,當(dāng)?shù)谝粭lDML語句執(zhí)行成功后乞娄,并不能將底層數(shù)據(jù)庫中的第一個(gè)賬戶的數(shù)據(jù)修改,只是將操作記錄了一下租漂;這個(gè)記錄是在內(nèi)存中完成的喇伯;當(dāng)?shù)诙lDML語句執(zhí)行成功后喊儡,和底層數(shù)據(jù)庫文件中的數(shù)據(jù)完成同步。若第二條DML語句執(zhí)行失敗稻据,則清空所有的歷史操作記錄艾猜,要完成以上的功能必須借助事務(wù)
三、事務(wù)四大特征(ACID)
原子性(A):事務(wù)是最小單位捻悯,不可再分
一致性(C):事務(wù)要求所有的DML語句操作的時(shí)候匆赃,必須保證同時(shí)成功或者同時(shí)失敗
隔離性(I):事務(wù)A和事務(wù)B之間具有隔離性
持久性(D):是事務(wù)的保證,事務(wù)終結(jié)的標(biāo)志(內(nèi)存的數(shù)據(jù)持久到硬盤文件中)
四今缚、關(guān)于事務(wù)的一些術(shù)語
開啟事務(wù):Start Transaction
事務(wù)結(jié)束:End Transaction
提交事務(wù):Commit Transaction
回滾事務(wù):Rollback Transaction
五算柳、和事務(wù)相關(guān)的兩條重要的SQL語句(TCL)
commit:提交
rollback:回滾
六、事務(wù)開啟的標(biāo)志姓言?事務(wù)結(jié)束的標(biāo)志瞬项?
開啟標(biāo)志:
- 任何一條DML語句(insert、update何荚、delete)執(zhí)行囱淋,標(biāo)志事務(wù)的開啟
結(jié)束標(biāo)志(提交或者回滾):
- 提交:成功的結(jié)束,將所有的DML語句操作歷史記錄和底層硬盤數(shù)據(jù)來一次同步
- 回滾:失敗的結(jié)束餐塘,將所有的DML語句操作歷史記錄全部清空
注意:mysql需要手動(dòng)打開事物(start transaction;)
七绎橘、事物與數(shù)據(jù)庫底層數(shù)據(jù)
在事物進(jìn)行過程中,未結(jié)束之前唠倦,DML語句是不會(huì)更改底層數(shù)據(jù)称鳞,只是將歷史操作記錄一下,在內(nèi)存中完成記錄稠鼻。只有在事物結(jié)束的時(shí)候冈止,而且是成功的結(jié)束的時(shí)候,才會(huì)修改底層硬盤文件中的數(shù)據(jù)
八候齿、在MySQL中熙暴,事務(wù)提交與回滾
在MySQL中,默認(rèn)情況下慌盯,事務(wù)是自動(dòng)提交的周霉,也就是說,只要執(zhí)行一條DML語句就開啟了事物亚皂,并且提交了事務(wù)
以上的自動(dòng)提交機(jī)制是可以關(guān)閉的
對(duì)t_user進(jìn)行提交和回滾操作
提交操作(事務(wù)成功)
start transaction
DML語句
commit
mysql> start transaction;#手動(dòng)開啟事務(wù)
mysql> insert into t_user(name) values('pp');
mysql> commit;#commit之后即可改變底層數(shù)據(jù)庫數(shù)據(jù)
mysql> select * from t_user;
id | name |
---|---|
1 | jay |
2 | man |
3 | pp |
3 rows in set (0.00 sec)
回滾操作(事務(wù)失敗)
start transaction
DML語句
rollback
mysql> start transaction;
mysql> insert into t_user(name) values('yy');
mysql> rollback;
mysql> select * from t_user;
id | name |
---|---|
1 | jay |
2 | man |
3 | pp |
3 rows in set (0.00 sec)
九俱箱、事務(wù)四大特性之一————隔離性(isolation)
事物A和事物B之間具有一定的隔離性
隔離性有隔離級(jí)別(4個(gè))
讀未提交:read uncommitted
讀已提交:read committed
可重復(fù)讀:repeatable read
串行化:serializable
1、 read uncommitted
- 事物A和事物B灭必,事物A未提交的數(shù)據(jù)狞谱,事物B可以讀取到
- 這里讀取到的數(shù)據(jù)叫做“臟數(shù)據(jù)”
- 這種隔離級(jí)別最低乃摹,這種級(jí)別一般是在理論上存在,數(shù)據(jù)庫隔離級(jí)別一般都高于該級(jí)別
公司發(fā)工資了跟衅,領(lǐng)導(dǎo)把5000元打到singo的賬號(hào)上孵睬,但是該事務(wù)并未提交,而singo正好去查看賬戶伶跷,發(fā)現(xiàn)工資已經(jīng)到賬掰读,是5000元整,非常高 興叭莫×字В可是不幸的是,領(lǐng)導(dǎo)發(fā)現(xiàn)發(fā)給singo的工資金額不對(duì)食寡,是2000元,于是迅速回滾了事務(wù)廓潜,修改金額后抵皱,將事務(wù)提交,最后singo實(shí)際的工資只有 2000元辩蛋,singo空歡喜一場(chǎng)呻畸。
出現(xiàn)上述情況,即我們所說的臟讀 悼院,兩個(gè)并發(fā)的事務(wù)伤为,“事務(wù)A:領(lǐng)導(dǎo)給singo發(fā)工資”、“事務(wù)B:singo查詢工資賬戶”据途,事務(wù)B讀取了事務(wù)A尚未提交的數(shù)據(jù)绞愚。
當(dāng)隔離級(jí)別設(shè)置為Read uncommitted 時(shí),就可能出現(xiàn)臟讀颖医,如何避免臟讀位衩,請(qǐng)看下一個(gè)隔離級(jí)別。
2熔萧、read committed
- 事物A和事物B糖驴,事物A提交的數(shù)據(jù),事物B才能讀取到
- 這種隔離級(jí)別高于讀未提交
- 換句話說佛致,對(duì)方事物提交之后的數(shù)據(jù)贮缕,我當(dāng)前事物才能讀取到
- 這種級(jí)別可以避免“臟數(shù)據(jù)”
- 這種隔離級(jí)別會(huì)導(dǎo)致“不可重復(fù)讀取”
- Oracle默認(rèn)隔離級(jí)別
singo拿著工資卡去消費(fèi),系統(tǒng)讀取到卡里確實(shí)有2000元俺榆,而此時(shí)她的老婆也正好在網(wǎng)上轉(zhuǎn)賬感昼,把singo工資卡的2000元轉(zhuǎn)到另一賬戶,并在 singo之前提交了事務(wù)罐脊,當(dāng)singo扣款時(shí)抑诸,系統(tǒng)檢查到singo的工資卡已經(jīng)沒有錢烂琴,扣款失敗,singo十分納悶蜕乡,明明卡里有錢奸绷,為 何......
出現(xiàn)上述情況,即我們所說的不可重復(fù)讀 层玲,兩個(gè)并發(fā)的事務(wù)号醉,“事務(wù)A:singo消費(fèi)”、“事務(wù)B:singo的老婆網(wǎng)上轉(zhuǎn)賬”辛块,事務(wù)A事先讀取了數(shù)據(jù)畔派,事務(wù)B緊接了更新了數(shù)據(jù),并提交了事務(wù)润绵,而事務(wù)A再次讀取該數(shù)據(jù)時(shí)线椰,數(shù)據(jù)已經(jīng)發(fā)生了改變。
當(dāng)隔離級(jí)別設(shè)置為Read committed 時(shí)尘盼,避免了臟讀憨愉,但是可能會(huì)造成不可重復(fù)讀。
大多數(shù)數(shù)據(jù)庫的默認(rèn)級(jí)別就是Read committed卿捎,比如Sql Server , Oracle配紫。如何解決不可重復(fù)讀這一問題,請(qǐng)看下一個(gè)隔離級(jí)別
3午阵、repeatable read
- 事務(wù)A和事務(wù)B躺孝,事務(wù)A提交之后的數(shù)據(jù),事務(wù)B讀取不到
- 事務(wù)B是可重復(fù)讀取數(shù)據(jù)
- 這種隔離級(jí)別高于讀已提交
- 換句話說底桂,對(duì)方提交之后的數(shù)據(jù)植袍,我還是讀取不到
- 這種隔離級(jí)別可以避免“不可重復(fù)讀取”,達(dá)到可重復(fù)讀取
- 比如1點(diǎn)和2點(diǎn)讀到數(shù)據(jù)是同一個(gè)
- MySQL默認(rèn)級(jí)別
- 雖然可以達(dá)到可重復(fù)讀取籽懦,但是會(huì)導(dǎo)致“幻像讀”
singo的老婆工作在銀行部門奋单,她時(shí)常通過銀行內(nèi)部系統(tǒng)查看singo的信用卡消費(fèi)記錄。有一天猫十,她正在查詢到singo當(dāng)月信用卡的總消費(fèi)金額 (select sum(amount) from transaction where month = 本月)為80元览濒,而singo此時(shí)正好在外面胡吃海塞后在收銀臺(tái)買單,消費(fèi)1000元拖云,即新增了一條1000元的消費(fèi)記錄(insert transaction ... )贷笛,并提交了事務(wù),隨后singo的老婆將singo當(dāng)月信用卡消費(fèi)的明細(xì)打印到A4紙上宙项,卻發(fā)現(xiàn)消費(fèi)總額為1080元乏苦,singo的老婆很詫異,以為出 現(xiàn)了幻覺,幻讀就這樣產(chǎn)生了汇荐。
注:Mysql的默認(rèn)隔離級(jí)別就是Repeatable read洞就。
4、serializable
- 事務(wù)A和事務(wù)B掀淘,事務(wù)A在操作數(shù)據(jù)庫時(shí)旬蟋,事務(wù)B只能排隊(duì)等待
- 這種隔離級(jí)別很少使用,吞吐量太低革娄,用戶體驗(yàn)差
- 這種級(jí)別可以避免“幻像讀”倾贰,每一次讀取的都是數(shù)據(jù)庫中真實(shí)存在數(shù)據(jù),事務(wù)A與事務(wù)B串行拦惋,而不并發(fā)
5匆浙、臟讀、不可重復(fù)讀厕妖、幻讀
1.臟讀:
臟讀就是指當(dāng)一個(gè)事務(wù)正在訪問數(shù)據(jù)首尼,并且對(duì)數(shù)據(jù)進(jìn)行了修改,而這種修改還沒有提交到數(shù)據(jù)庫中言秸,這時(shí)软能,另外一個(gè)事務(wù)也訪問這個(gè)數(shù)據(jù),然后使用了這個(gè)數(shù)據(jù)井仰。
2.不可重復(fù)讀:
是指在一個(gè)事務(wù)內(nèi),多次讀同一數(shù)據(jù)破加。在這個(gè)事務(wù)還沒有結(jié)束時(shí)俱恶,另外一個(gè)事務(wù)也訪問該同一數(shù)據(jù)。那么范舀,在第一個(gè)事務(wù)中的兩次讀數(shù)據(jù)之間合是,由于第二個(gè)事務(wù)的修改,那么第一個(gè)事務(wù)兩次讀到的的數(shù)據(jù)可能是不一樣的锭环。這樣就發(fā)生了在一個(gè)事務(wù)內(nèi)兩次讀到的數(shù)據(jù)是不一樣的聪全,因此稱為是不可重復(fù)讀。(即不能讀到相同的數(shù)據(jù)內(nèi)容)
例如辅辩,一個(gè)編輯人員兩次讀取同一文檔难礼,但在兩次讀取之間,作者重寫了該文檔玫锋。當(dāng)編輯人員第二次讀取文檔時(shí)蛾茉,文檔已更改。原始讀取不可重復(fù)撩鹿。如果只有在作者全部完成編寫后編輯人員才可以讀取文檔谦炬,則可以避免該問題。
3.幻讀:
是指當(dāng)事務(wù)不是獨(dú)立執(zhí)行時(shí)發(fā)生的一種現(xiàn)象,例如第一個(gè)事務(wù)對(duì)一個(gè)表中的數(shù)據(jù)進(jìn)行了修改键思,這種修改涉及到表中的全部數(shù)據(jù)行础爬。同時(shí),第二個(gè)事務(wù)也修改這個(gè)表中的數(shù)據(jù)吼鳞,這種修改是向表中插入一行新數(shù)據(jù)看蚜。那么,以后就會(huì)發(fā)生操作第一個(gè)事務(wù)的用戶發(fā)現(xiàn)表中還有沒有修改的數(shù)據(jù)行赖条,就好象
發(fā)生了幻覺一樣失乾。
例如,一個(gè)編輯人員更改作者提交的文檔纬乍,但當(dāng)生產(chǎn)部門將其更改內(nèi)容合并到該文檔的主復(fù)本時(shí)碱茁,發(fā)現(xiàn)作者已將未編輯的新材料添加到該文檔中。如果在編輯人員和生產(chǎn)部門完成對(duì)原始文檔的處理之前仿贬,任何人都不能將新材料添加到文檔中纽竣,則可以避免該問題。
十茧泪、隔離級(jí)別與一致性關(guān)系
十一蜓氨、設(shè)置事務(wù)隔離級(jí)別
方式一
可以在my.ini(windows)、my.cnf(linux)文件中使用transaction-isolation選項(xiàng)來設(shè)置服務(wù)器的缺省事務(wù)隔離級(jí)別队伟。
該選項(xiàng)值可以是:
– READ-UNCOMMITTED
– READ-COMMITTED
– REPEATABLE-READ
– SERIALIZABLE
? 例如:
[mysqld]
transaction-isolation = READ-COMMITTED
方式二
通過命令動(dòng)態(tài)設(shè)置隔離級(jí)別
? 隔離級(jí)別也可以在運(yùn)行的服務(wù)器中動(dòng)態(tài)設(shè)置穴吹,應(yīng)使用SET TRANSACTION ISOLATION LEVEL語句。
? 其語法模式為:
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL <isolation-level>
其中的<isolation-level>可以是:
– READ UNCOMMITTED
– READ COMMITTED
– REPEATABLE READ
– SERIALIZABLE
? 例如: SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
十二嗜侮、隔離級(jí)別的作用范圍
? 事務(wù)隔離級(jí)別的作用范圍分為兩種:
– 全局級(jí):對(duì)所有的會(huì)話有效
– 會(huì)話級(jí):只對(duì)當(dāng)前的會(huì)話有效
? 例如港令,設(shè)置會(huì)話級(jí)隔離級(jí)別為READ COMMITTED :
mysql> SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
或:
mysql> SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED锈颗;
? 設(shè)置全局級(jí)隔離級(jí)別為READ COMMITTED :
mysql> SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED顷霹;
十三、查看隔離級(jí)別
mysql中:
查看本連接的隔離級(jí)別:select @@tx_isolation;
查看整體的隔離級(jí)別:select @@global.tx_isolation;