nodejs做網(wǎng)站容易被攻擊嗎網(wǎng)站外部?jī)?yōu)化的4大重點(diǎn)
MVCC是一種用來解決讀寫沖突的無鎖并發(fā)控制,也就是為事務(wù)分配單項(xiàng)增長(zhǎng)的時(shí)間戳,為每個(gè)修改保存一個(gè)版本,版本與事務(wù)時(shí)間戳關(guān)聯(lián),讀操作只讀該事務(wù)開始前的數(shù)據(jù)庫(kù)的快照
MVCC,全稱Multi-Version Concurrency Control,即多版本并發(fā)控制。MVCC是一種并發(fā)控制的方法,一般在數(shù)據(jù)庫(kù)管理系統(tǒng)中,實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的并發(fā)訪問,在編程語言中實(shí)現(xiàn)事務(wù)內(nèi)存。
MVCC在MySQL InnoDB中的實(shí)現(xiàn)主要是為了提高數(shù)據(jù)庫(kù)并發(fā)性能,用更好的方式去處理讀寫沖突,做到即使有讀寫沖突時(shí),也能做到不加鎖,非阻塞并發(fā)讀。
當(dāng)前讀
像select lock in share mode(共享鎖), select for update ; update, insert ,delete(排他鎖)這些操作都是一種當(dāng)前讀,為什么叫當(dāng)前讀?就是它讀取的是記錄的最新版本,讀取時(shí)還要保證其他并發(fā)事務(wù)不能修改當(dāng)前記錄,會(huì)對(duì)讀取的記錄進(jìn)行加鎖。
快照讀(提高數(shù)據(jù)庫(kù)的并發(fā)查詢能力)
像不加鎖的select操作就是快照讀,即不加鎖的非阻塞讀;快照讀的前提是隔離級(jí)別不是串行級(jí)別,串行級(jí)別下的快照讀會(huì)退化成當(dāng)前讀;之所以出現(xiàn)快照讀的情況,是基于提高并發(fā)性能的考慮,快照讀的實(shí)現(xiàn)是基于多版本并發(fā)控制,即MVCC,可以認(rèn)為MVCC是行鎖的一個(gè)變種,但它在很多情況下,避免了加鎖操作,降低了開銷;既然是基于多版本,即快照讀可能讀到的并不一定是數(shù)據(jù)的最新版本,而有可能是之前的歷史版本
當(dāng)前讀、快照讀、MVCC關(guān)系
MVCC多版本并發(fā)控制指的是維持一個(gè)數(shù)據(jù)的多個(gè)版本,使得讀寫操作沒有沖突,快照讀是MySQL為實(shí)現(xiàn)MVCC的一個(gè)非阻塞讀功能。MVCC模塊在MySQL中的具體實(shí)現(xiàn)是由三個(gè)隱式字段,undo日志、read view三個(gè)組件來實(shí)現(xiàn)的
解決以下問題
1、在并發(fā)讀寫數(shù)據(jù)庫(kù)時(shí),可以做到在讀操作時(shí)不用阻塞寫操作,寫操作也不用阻塞讀操作,提高了數(shù)據(jù)庫(kù)并發(fā)讀寫的性能
2、解決臟讀、幻讀、不可重復(fù)讀等事務(wù)隔離問題,但是不能解決更新丟失問題
幻讀等問題詳情
實(shí)現(xiàn)原理
主要依賴于記錄中的三個(gè)隱藏字段,undolog,read view來實(shí)現(xiàn)的。
隱藏字段
每行記錄除了我們自定義的字段外,還有數(shù)據(jù)庫(kù)隱式定義的DB_TRX_ID,DB_ROLL_PTR,DB_ROWID等字段
DB_TRX_ID
6字節(jié),最近修改事務(wù)id,記錄創(chuàng)建這條記錄或者最后一次修改該記錄的事務(wù)id
DB_ROLL_PTR
7字節(jié),回滾指針,指向這條記錄的上一個(gè)版本,用于配合undolog,指向上一個(gè)舊版本
DB_ROW_D
6字節(jié),隱藏的主鍵,如果數(shù)據(jù)表沒有主鍵,那么innodb會(huì)自動(dòng)生成一個(gè)6字節(jié)的rowid
undo log
undolog被稱之為回滾日志,表示在進(jìn)行insert,delete, update操作的時(shí)候產(chǎn)生的方便回滾的日志
當(dāng)進(jìn)行insert操作的時(shí)候,產(chǎn)生的undolog只在事務(wù)回滾的時(shí)候需要,并且在事務(wù)提交之后可以被立刻丟棄當(dāng)進(jìn)行update和delete操作的時(shí)候,產(chǎn)生的undolog不僅僅在事務(wù)回滾的時(shí)候需要,在快照讀的時(shí)候也需要,所以不能隨便刪除,只有在快照讀或事務(wù)回滾不涉及該日志時(shí),對(duì)應(yīng)的日志才會(huì)被purge線程統(tǒng)一清除(當(dāng)數(shù)
據(jù)發(fā)生更新和刪除操作的時(shí)候都只是設(shè)置一下老記錄的deleted_bit,并不是真正的將過時(shí)的記錄刪除,因?yàn)闉榱斯?jié)省磁盤空間,innodb有專門的purge線程來清除deleted_bit為true的記錄,如果某個(gè)記錄的deleted_id為true,并且DB_TRX_ID相對(duì)于purge線程的read view 可見,那么這條記錄一定時(shí)可以被清除的)
Read View
Read View是事務(wù)進(jìn)行快照讀操作的時(shí)候生產(chǎn)的讀視圖,在該事務(wù)執(zhí)行快照讀的那一刻,會(huì)生成一個(gè)數(shù)據(jù)系統(tǒng)當(dāng)前的快照,記錄并維護(hù)系統(tǒng)當(dāng)前活躍事務(wù)的id,事務(wù)的id值是遞增的。
其實(shí)Read View的最大作用是用來做可見性判斷的,也就是說當(dāng)某個(gè)事務(wù)在執(zhí)行快照讀的時(shí)候,對(duì)該記錄創(chuàng)建一個(gè)Read View的視圖,把它當(dāng)作條件去判斷當(dāng)前事務(wù)能夠看到哪個(gè)版本的數(shù)據(jù),有可能讀取到的是最新的數(shù)據(jù),也有可能讀取的是當(dāng)前行記錄的undolog中某個(gè)版本的數(shù)據(jù)
Read View遵循的可見性算法主要是將要被修改的數(shù)據(jù)的最新記錄中的DB_TRX_ID(當(dāng)前事務(wù)id)取出來,與系統(tǒng)當(dāng)前其他活躍事務(wù)的id去對(duì)比,如果DB_TRX_ID跟Read View的屬性做了比較,不符合可見性,那么就通過DB_ROLL_PTR回滾指針去取出undolog中的DB_TRX_ID做比較,即遍歷鏈表中的DB_TRX_ID,直到找到滿足條件的DB_TRX_ID,這個(gè)DB_TRX_ID所在的舊記錄就是當(dāng)前事務(wù)能看到的最新老版本數(shù)據(jù)。
Read View的可見性規(guī)則如下所示:
首先要知道Read View中的三個(gè)全局屬性:
trx_list:一個(gè)數(shù)值列表,用來維護(hù)Read View生成時(shí)刻系統(tǒng)正活躍的事務(wù)ID(1,2,3)
up_limit_id:記錄trx_list列表中事務(wù)ID最小的ID(1)
low_limit_id:Read View生成時(shí)刻系統(tǒng)尚未分配的下一個(gè)事務(wù)ID,(4)
具體的比較規(guī)則如下:
1、首先比較DB_TRX_ID<up_limit_id,如果小于,則當(dāng)前事務(wù)能看到DB_TRX_ID所在的記錄,如果大于等于進(jìn)入下一個(gè)判斷
2、接下來判斷DB_TRX_ID>= low_limit_id,如果大于等于則代表DB_TRX_ID所在的記錄在Read View生成后才出現(xiàn)的,那么對(duì)于當(dāng)前事務(wù)肯定不可見,如果小于,則進(jìn)入下一步判斷
3、判斷DB_TRX_ID是否在活躍事務(wù)中,如果在,則代表在Read View生成時(shí)刻,這個(gè)事務(wù)還是活躍狀態(tài),還沒有commit,修改的數(shù)據(jù),當(dāng)前事務(wù)也是看不到,如果不在,則說明這個(gè)事務(wù)在Read View生成之前就已經(jīng)開始commit,那么修改的結(jié)果是能夠看見的。
RC、RR級(jí)別下的InnoDB快照讀有什么不同
因?yàn)镽ead View生成時(shí)機(jī)的不同,從而造成RC、RR級(jí)別下快照讀的結(jié)果的不同
1、在RR級(jí)別下的某個(gè)事務(wù)的對(duì)某條記錄的第一次快照讀會(huì)創(chuàng)建一個(gè)快照即Read View,將當(dāng)前系統(tǒng)活躍的其他事務(wù)記錄起來,此后在調(diào)用快照讀的時(shí)候,還是使用的是同一個(gè)Read View,所以只要當(dāng)前事務(wù)在其他事務(wù)提交更新之前使用過快照讀,那么之后的快照讀使用的都是同一個(gè)Read View,所以對(duì)之后的修改不可見
2、在RR級(jí)別下,快照讀生成ead View時(shí),Read View會(huì)記錄此時(shí)所有其他活動(dòng)和事務(wù)的快照,這些事務(wù)的修改對(duì)于當(dāng)前事務(wù)都是不可見的,而早于Read View創(chuàng)建的事務(wù)所做的修改均是可見
3、在RC級(jí)別下,事務(wù)中,每次快照讀都會(huì)新生成一個(gè)快照和Read View,這就是我們?cè)赗C級(jí)別下的事務(wù)中可以看到別的事務(wù)提交的更新的原因。
總結(jié):在RC隔離級(jí)別下,是每個(gè)快照讀都會(huì)生成并獲取最新的Read View,而在RR隔離級(jí)別下,則是同一個(gè)事務(wù)中的第一個(gè)快照讀才會(huì)創(chuàng)建Read View,之后的快照讀獲取的都是同一個(gè)Read View.