事務(wù)是指將一個(gè)業(yè)務(wù)流程中對(duì)數(shù)據(jù)庫(kù)的多次操作綁定在一起,使其成為一個(gè)最小的執(zhí)行顆粒,當(dāng)這些操作中某一個(gè)失敗了,整個(gè)流程也會(huì)失敗,這樣做能防止數(shù)據(jù)庫(kù)數(shù)據(jù)不一致等問(wèn)題.
事務(wù)有以下幾個(gè)特征(ACID):
原子性(A: atomicity)
一個(gè)事務(wù)是一個(gè)最小的執(zhí)行顆粒,不可再分,整個(gè)事務(wù)要么都成功,要么都失敗.一致性(C:consistency)
<沒(méi)理解,感覺(jué)更像是原子性的一個(gè)補(bǔ)充>隔離性(I:isolaton)
一個(gè)事務(wù)在未提交前對(duì)其它事務(wù)都是不可見(jiàn)的,其它事務(wù)不能訪問(wèn)未提交事務(wù)修改的數(shù)據(jù).持久性(D:durability)
一旦事務(wù)提交,其所作的修改都會(huì)持久保存下來(lái).
在數(shù)據(jù)庫(kù)中,實(shí)現(xiàn)了ACID的數(shù)據(jù)庫(kù)比未實(shí)現(xiàn)了要消耗更多的CPU 和硬盤資源.
在mysql中,可以通過(guò)對(duì)autocommit
參數(shù)的修改來(lái)開(kāi)啟或者關(guān)閉自動(dòng)提交,當(dāng)其為0時(shí)表示關(guān)閉自動(dòng)提交,這時(shí)候在執(zhí)行sql語(yǔ)句時(shí)需要手動(dòng)在末尾執(zhí)行commit
或rollback
來(lái)提交或者回滾事務(wù).修改autocommit
參數(shù)的方式為set autocommit=0;
另外,還可以在執(zhí)行語(yǔ)句前加上start tranaction;
來(lái)開(kāi)啟一個(gè)事務(wù),其優(yōu)先級(jí)大于autocommit
,即使autocommit
為1,也會(huì)開(kāi)啟事務(wù).
1.3.1 事務(wù)的隔離級(jí)別
在數(shù)據(jù)庫(kù)中有如下四種隔離級(jí)別:
read uncommitted(未提交度)
是指讀取其它事務(wù)未提交的數(shù)據(jù),這樣會(huì)造成造成臟讀,因?yàn)榭赡軙?huì)讀取到其它事務(wù)最終回滾掉的垃圾數(shù)據(jù)或者未處理完成的數(shù)據(jù).read commit(提交讀)
每次讀取到的都是其它事務(wù)提交的數(shù)據(jù),這樣有個(gè)問(wèn)題是會(huì)造成在同一個(gè)事務(wù)中多次對(duì)同一個(gè)數(shù)據(jù)讀取,由于在讀取期間其它事務(wù)對(duì)同一條數(shù)據(jù)進(jìn)行了修改提交,這樣會(huì)造成同一個(gè)數(shù)據(jù)庫(kù)中的多次讀取數(shù)據(jù)不一樣,即不可重復(fù)讀.repeatable read(可重復(fù)讀)
此級(jí)別保證了在同一個(gè)事務(wù)中的多次讀取到的數(shù)據(jù)都是相同的,但這樣會(huì)出現(xiàn)幻讀,它是當(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)表中還有沒(méi)有修改的數(shù)據(jù)行仆抵,就好象發(fā)生了幻覺(jué)一樣甫窟。
可重復(fù)讀是mysql默認(rèn)的事務(wù)隔離級(jí)別,其使用了MVCC解決了幻讀的問(wèn)題.serializable (可串行化)
此界別是將事務(wù)的執(zhí)行全部串行化,既禁止對(duì)同一個(gè)數(shù)據(jù)的并發(fā)讀取,主要是使用鎖來(lái)實(shí)現(xiàn).此級(jí)別是最高隔離界別,會(huì)出現(xiàn)大量的鎖的爭(zhēng)用和超時(shí)問(wèn)題,只有在確保數(shù)據(jù)一致性和可以接受沒(méi)有并發(fā)的情況下才考慮用戶此級(jí)別.
隔離級(jí)別 | 臟讀可能性 | 不可重復(fù)讀可能性 | 幻讀可能性 | 加鎖讀 |
---|---|---|---|---|
read uncommitted | yes | yes | yes | no |
read commit | no | yes | yes | no |
repeatable read | no | no | yes | no |
serializable | no | no | no | yes |
1.3.2 死鎖
死鎖是指當(dāng)多個(gè)事務(wù)在同一個(gè)資源上相互占用,并請(qǐng)求鎖定對(duì)方占用的資源,從而導(dǎo)致的惡性循環(huán)現(xiàn)象.例如:
- 事務(wù) 1
start stranaction;
update user set user_name ='A' where user_id=1;
update user set user_name ='B' where user_id=2;
commit;
- 事務(wù) 2
start stranaction;
update user set user_name ='C' where user_id=2;
update user set user_name ='D' where user_id=1;
commit;
在上面的兩個(gè)事務(wù)中,若兩個(gè)事務(wù)都執(zhí)行了第一個(gè)update
語(yǔ)句,這時(shí)候這兩行數(shù)據(jù)都被鎖定,這時(shí)候再執(zhí)行第二個(gè)update
語(yǔ)句,就會(huì)出現(xiàn)死鎖現(xiàn)象.
在mysql的innodb中處理死鎖的方式是當(dāng)檢測(cè)到死鎖發(fā)生時(shí),將持有最少行級(jí)排它鎖的事務(wù)進(jìn)行回滾.對(duì)于事務(wù)性數(shù)據(jù)庫(kù),死鎖是無(wú)法避免的.
1.3.3 事務(wù)日志
事務(wù)日志是在事務(wù)數(shù)據(jù)庫(kù)中,一次事務(wù)的操作修改的是數(shù)據(jù)表的內(nèi)存拷貝部分,然后在提交數(shù)據(jù)后,數(shù)據(jù)庫(kù)再將這部分?jǐn)?shù)據(jù)拷貝寫到數(shù)據(jù)庫(kù)中,既對(duì)數(shù)據(jù)表的一次修改操作設(shè)計(jì)的是硬盤的兩次讀寫.當(dāng)數(shù)據(jù)拷貝時(shí)突然發(fā)生斷電,下次再啟動(dòng)時(shí),數(shù)據(jù)庫(kù)會(huì)再?gòu)木彺嬷袑?shù)據(jù)拷貝到數(shù)據(jù)表中,目前mysql采用的是這樣的方式.
1.3.4 mysql中的事務(wù)
msyql中提供了兩種事務(wù)型數(shù)據(jù)庫(kù)引擎: Innodb 和 NDB Cluster.
- 自動(dòng)提交
在mysql中autocommit
是默認(rèn)開(kāi)著的,即默認(rèn)自動(dòng)提交,可以使用下面命令查看
show variables like 'autocommit
可使用set autocommit=1
來(lái)修改其狀態(tài).
mysql 可以通過(guò)以下命令修改隔離級(jí)別
set session tranaction isoltion level <read committed>