數(shù)據(jù)庫(kù)的事務(wù)
什么是數(shù)據(jù)庫(kù)的事務(wù)谴古?
數(shù)據(jù)庫(kù)事務(wù)(transaction)是訪問并發(fā)可能操作各種數(shù)據(jù)項(xiàng)的一個(gè)數(shù)據(jù)庫(kù)操作序列掰担,這次操作要么全部執(zhí)行带饱,要么全部不執(zhí)行,是一個(gè)不可分割的工作單位勺疼,事務(wù)由事務(wù)開始與事務(wù)結(jié)束之間執(zhí)行的全書數(shù)據(jù)庫(kù)操作組成捏鱼。
事務(wù)的四大特性是什么穷躁?
原子性:原子性是指包含事務(wù)的操作要么全部執(zhí)行成功问潭,要么全部失敗回滾狡忙。
一致性:一致性是指事務(wù)在執(zhí)行前后狀態(tài)是一致的
隔離性:一個(gè)事務(wù)進(jìn)行的修改在最終提交之前灾茁,對(duì)其他的事務(wù)是不可見的
持久性: 數(shù)據(jù)一旦提交,其所作的修改將永久地保存在數(shù)據(jù)庫(kù)中
數(shù)據(jù)庫(kù)并發(fā)的一致性問題禀挫?
當(dāng)多個(gè)事務(wù)并發(fā)執(zhí)行時(shí)语婴,可能會(huì)出現(xiàn)以下問題:
臟讀:事務(wù)A更新了數(shù)據(jù)砰左,但還沒有提交场航,這時(shí)事務(wù)B讀取到事務(wù)A更新后的數(shù)據(jù)溉痢,然后事務(wù)A回滾了适室,事務(wù)B讀取到的數(shù)據(jù)就成為了臟數(shù)據(jù)。
不可重復(fù)讀:事務(wù)A對(duì)數(shù)據(jù)進(jìn)行多次讀取蔬螟,事務(wù)B在事務(wù)A多次讀取的過程中執(zhí)行了更新操作并提交了旧巾,導(dǎo)致事務(wù)A多次讀取到的數(shù)據(jù)并不一致鲁猩。
幻讀:事務(wù)A在讀取數(shù)據(jù)后罢坝,事務(wù)B向事務(wù)A讀取的數(shù)據(jù)中插入了幾條數(shù)據(jù),事務(wù)A再次讀取數(shù)據(jù)時(shí)發(fā)現(xiàn)多了幾條數(shù)據(jù)男应,和之前讀取的數(shù)據(jù)不一致
數(shù)據(jù)庫(kù)的隔離級(jí)別有哪些沐飘?
未提交讀:一個(gè)事務(wù)在提交前牲迫,他的修改對(duì)其他事務(wù)是可見的
提交讀:一個(gè)事務(wù)提交之后盹憎,他的修改才能被其他事務(wù)看到
可重復(fù)讀: 在同一個(gè)事務(wù)中多次讀取到的數(shù)據(jù)是一致的
串行化:需要加鎖實(shí)現(xiàn),會(huì)強(qiáng)制事務(wù)串行執(zhí)行
隔離級(jí)別 臟讀 不可重復(fù)讀 幻讀
未提交讀 允許 允許 允許
提交讀 不允許 允許 允許
可重復(fù)讀 不允許 不允許 允許
串行化 不允許 不允許 不允許
mysql 默認(rèn)的隔離級(jí)別是 可重復(fù)讀
隔離級(jí)別是如何實(shí)現(xiàn)的?
事務(wù)的隔離機(jī)制主要是依靠鎖機(jī)制和MVCC(多版本并發(fā)控制)實(shí)現(xiàn)的奶稠,提交讀和可重復(fù)讀可以通過MVCC實(shí)現(xiàn)锌订,串行化可以通過鎖機(jī)制實(shí)現(xiàn)
什么是MVCC?
MVCC( multiple version concurrent control )是一種控制并發(fā)的方法啦辐,主要用來提高數(shù)據(jù)庫(kù)的并發(fā)性能
在了解MVCC時(shí)應(yīng)該先了解當(dāng)前讀和快照讀
當(dāng)前讀:讀取的是數(shù)據(jù)庫(kù)的最新版本芹关,并且在讀取時(shí)保證其他事務(wù)不會(huì)修改當(dāng)前的記錄侥衬,所以會(huì)對(duì)讀取的數(shù)據(jù)加鎖跑芳。
快照讀:不加鎖的讀取操作即為快照讀博个,使用MVCC來讀取快照中的數(shù)據(jù),避免加鎖帶來的性能損耗
可以看到MVCC的作用是在不加鎖的情況下往堡,解決數(shù)據(jù)讀寫沖突問題,并且解決臟讀养葵、幻讀、不可重復(fù)讀等問題佃蚜,但是不能解決丟失修改問題谐算。
MVCC的實(shí)現(xiàn)原理:
版本號(hào):
系統(tǒng)版本號(hào):是一個(gè)自增的ID,每開啟一個(gè)事務(wù)斤儿,系統(tǒng)版本號(hào)都會(huì)自增
事務(wù)版本號(hào):事務(wù)版本號(hào)就是事務(wù)開始時(shí)的系統(tǒng)版本號(hào)往果,可以通過事務(wù)版本號(hào)的大小判斷事務(wù)的時(shí)間順序
行記錄隱藏的列
DB_ROW_ID:所需空軍6byte陕贮,隱含的自增ID潘飘,用來生產(chǎn)聚簇索引,如果數(shù)據(jù)表沒有指定的聚簇索引戈擒,InnoDB會(huì)利用這個(gè)隱藏的id 創(chuàng)建聚簇索引
DB_TRX_ID:所需空間6byte,最近修改的事務(wù)ID筐高,記錄創(chuàng)建這條記錄或最后一次修改這條記錄的事務(wù)ID
DB_Roll_PTR: 所需空間7byte,回滾指針现喳,指向這條記錄的上一個(gè)版本
undo日志
mvcc做使用到的快照會(huì)存儲(chǔ)到Undo日志中,該日志通過回滾指針將一個(gè)一個(gè)數(shù)據(jù)行的所有快照連接起來冰单。
在重復(fù)讀的隔離級(jí)別下诫欠,innodb的工作流程:
SELECT
作為查詢結(jié)果要滿足兩個(gè)條件:
當(dāng)前事務(wù)所要查詢的數(shù)據(jù)行快照的創(chuàng)建版本號(hào)必須小于當(dāng)前事務(wù)的版本號(hào),這樣做的目的是保證當(dāng)前事務(wù)讀取的數(shù)據(jù)行的快照要么在當(dāng)前事務(wù)開始前就已經(jīng)存在轿偎,要么就是當(dāng)前事務(wù)自身插入或者修改過的
當(dāng)前事務(wù)所要讀取的數(shù)據(jù)行快照的刪除版本號(hào)必須大雨當(dāng)前事務(wù)的版本號(hào)被廓,如果是小于等于的話嫁乘,表示該數(shù)據(jù)行快照已經(jīng)被刪除,不能讀取
INSERT
將當(dāng)前系統(tǒng)版本號(hào)作為數(shù)據(jù)行快照的創(chuàng)建版本號(hào)
DELETE
將當(dāng)前系統(tǒng)版本號(hào)作為數(shù)據(jù)行快照的刪除版本號(hào)
UPDATE
保存當(dāng)前系統(tǒng)版本號(hào)為更新前數(shù)據(jù)行快照創(chuàng)建的行版本號(hào)仓蛆,并保存當(dāng)前系統(tǒng)版本號(hào)為更新后的數(shù)據(jù)行快照的刪除版本號(hào)看疙,其實(shí)就是能庆,先刪除在插入即為更新
總計(jì)一下,MVCC的作用就是在避免枷鎖的情況下相味,最大限度的解決讀寫并發(fā)沖突的問題丰涉,他可以實(shí)現(xiàn)提交讀和可重復(fù)讀的兩個(gè)隔離級(jí)一死。
數(shù)據(jù)庫(kù)的鎖
什么是數(shù)據(jù)庫(kù)的鎖傻唾?
當(dāng)數(shù)據(jù)庫(kù)有并發(fā)事務(wù)的時(shí)候,保證數(shù)據(jù)訪問順序的機(jī)制稱之為鎖機(jī)制
數(shù)據(jù)庫(kù)的鎖與隔離級(jí)別的關(guān)系伪煤?
隔離級(jí)別 實(shí)現(xiàn)方式
未提交讀 總是讀取最新的數(shù)據(jù)抱既,無需加鎖
提交讀 讀取數(shù)據(jù)時(shí)加共享鎖扁誓,讀取數(shù)據(jù)后釋放共享鎖
可重復(fù)讀 讀取數(shù)據(jù)時(shí)加共享鎖,事務(wù)結(jié)束后釋放共享鎖
串行化 鎖定整個(gè)范圍健足删,一直持有鎖到事務(wù)結(jié)束
數(shù)據(jù)庫(kù)鎖的類型有哪些失受?
按照鎖的粒度可以將mysql鎖分為三種:
mysql 鎖級(jí)別 資源開銷 加速鎖速度 是否會(huì)出現(xiàn)死鎖 鎖的粒度 并發(fā)度
表級(jí)鎖 小 快 不會(huì) 大 低
行級(jí)鎖 大 慢 會(huì) 小 高
頁(yè)面鎖 一般 一般 不會(huì) 一般 一般
Myisam 默認(rèn)采用表級(jí)鎖贱纠,innoDB默認(rèn)采用行級(jí)鎖
從鎖的類別上區(qū)別可以分為共享鎖和排他鎖
共享鎖:共享鎖又稱讀鎖响蕴,簡(jiǎn)稱為S鎖浦夷,一個(gè)事務(wù)對(duì)一個(gè)數(shù)據(jù)對(duì)象加了S鎖辜王,可以對(duì)這個(gè)對(duì)象進(jìn)行讀去操作呐馆,但不能進(jìn)行更新操作,并且在加鎖期間其他事務(wù)只能對(duì)這個(gè)數(shù)據(jù)對(duì)象加S鎖续膳,不能加X鎖收班。
排他鎖:排他鎖又稱為寫鎖,簡(jiǎn)稱X鎖社付,一個(gè)事務(wù)對(duì)一個(gè)數(shù)據(jù)對(duì)象加了X鎖邻耕,可以對(duì)這個(gè)對(duì)象進(jìn)行讀取和更新操作兄世,加鎖期間碘饼,其他事務(wù)不能對(duì)該數(shù)據(jù)對(duì)象晉西加X鎖或S鎖
mysql 中InnoDB 引擎的行鎖模式及其是如何實(shí)現(xiàn)的
行鎖模式
在存在行鎖和表鎖的情況下悲伶,一個(gè)事務(wù)想對(duì)某個(gè)表加X鎖時(shí)麸锉,需要先檢查是否有其他事務(wù)對(duì)這個(gè)表加了鎖或?qū)@個(gè)表的某一行加了鎖花沉,對(duì)表的每一行都進(jìn)行檢測(cè)一次是非常低效率的碱屁,為了解決這種問題蛾找,實(shí)現(xiàn)多粒度鎖機(jī)制打毛,InnDB還有兩種內(nèi)部使用的意向鎖幻枉,兩種意向鎖都是表鎖。
意向共享鎖:簡(jiǎn)稱IS鎖胰挑,一個(gè)事務(wù)打算給數(shù)據(jù)行加共享鎖前必須先獲得該表的IS鎖
意向排他鎖:簡(jiǎn)稱IX鎖瞻颂,一個(gè)事務(wù)打算給數(shù)據(jù)行加排他鎖前必須先獲得該表的IX鎖
有了意向鎖蘸朋,一個(gè)事務(wù)想對(duì)某個(gè)表加X鎖藕坯,只要檢查是否有其他事務(wù)對(duì)這個(gè)表加了X/IX/S/IS鎖即可噪沙。
行鎖的實(shí)現(xiàn)方式:INnDB 行鎖主要分三種情況:
對(duì)索引加鎖
對(duì)索引之間的間隙正歼,第一條記錄前的間隙或最后一條后的間隙加鎖
前兩中放入組合局义,對(duì)記錄及前面的間隙枷鎖
innoDB 行鎖的特性:如果不通過索引條件檢索數(shù)據(jù)喜爷,那么innoDB將對(duì)表中所有記錄加鎖,實(shí)際產(chǎn)生的效果和表鎖一樣
MVCC不能解決幻讀問題术幔,在可重復(fù)讀隔離級(jí)別下诅挑,使用MVCC +Next-key Locks可以解決幻讀問題
什么是數(shù)據(jù)庫(kù)的樂觀鎖和悲觀鎖拔妥,如何實(shí)現(xiàn)没龙?
樂觀鎖兜畸;系統(tǒng)假設(shè)數(shù)據(jù)的更新在大多數(shù)時(shí)候不會(huì)產(chǎn)生沖突的,所以數(shù)據(jù)庫(kù)只在更新數(shù)據(jù)操作提交的時(shí)候?qū)?shù)據(jù)檢測(cè)沖突煞躬,如果存在沖突恩沛,則更新數(shù)據(jù)失敗
樂觀鎖實(shí)現(xiàn)方式:一般通過版本號(hào)和CAS 算法實(shí)現(xiàn)
悲觀鎖:假定會(huì)發(fā)生沖突雷客,屏蔽一切可能違反數(shù)據(jù)完整性的操作搅裙,通俗講就是每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改部逮,所以每次都在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖兄朋。
悲觀鎖的實(shí)現(xiàn)方式: 通過數(shù)據(jù)庫(kù)的鎖機(jī)制實(shí)現(xiàn),對(duì)查詢語(yǔ)句添加 for updata
什么死鎖怜械?如何避免颅和?
死鎖是指兩個(gè)或者兩個(gè)以上的進(jìn)程在執(zhí)行過程中傅事,由于競(jìng)爭(zhēng)資源或者由于彼此通信而早造成的一種阻塞現(xiàn)象,在mysql 中峡扩,Myisam是一次獲取所需的全部鎖蹭越,要么全部滿足,要么全部等待有额,所以不會(huì)出現(xiàn)死鎖般又。在Innodb存儲(chǔ)引擎中,除了三個(gè)SQL組成的事務(wù)外巍佑,鎖都是逐步獲得的茴迁,所以存在死鎖的問題。
如何避免mysql 發(fā)生死鎖或鎖沖突萤衰?
如果不通的程序并發(fā)存取多個(gè)表,盡量以相同的順序訪問表
在程序以批量方式處理數(shù)據(jù)的時(shí)候怕膛,如果已經(jīng)對(duì)數(shù)據(jù)排序椅邓,盡量保證每個(gè)縣城按照固定的順序來處理記錄
在事務(wù)中,如果需要更新記錄,應(yīng)直接申請(qǐng)足夠級(jí)別的排他鎖茬底,而不應(yīng)該先申請(qǐng)共享鎖,更新時(shí)在申請(qǐng)排他鎖,因?yàn)樵诋?dāng)前用戶申請(qǐng)排他鎖時(shí),其他事務(wù)可能已經(jīng)獲得了相同記錄的共享鎖帮坚,從而造成鎖沖突或者死鎖纫普。
盡量使用較低的隔離級(jí)別
盡量使用索引訪問數(shù)據(jù),是加鎖更加準(zhǔn)確,從而減少鎖沖突的機(jī)會(huì)
合理選擇事務(wù)的大小,小事務(wù)發(fā)生鎖沖突的概率更低
盡量用相等的條件訪問數(shù)據(jù),可以避免Next-key 鎖對(duì)并發(fā)插入的影響
不要申請(qǐng)超過十幾需要的鎖級(jí)別,查詢時(shí)盡量不顯示加鎖
對(duì)于一些特定的事務(wù),可以表鎖來提高處理速度或減少死鎖的概率