一、為什么一個事務(wù)能讀取到其他事務(wù)修改后未提交的數(shù)據(jù)
在沒有正式提交之前,數(shù)據(jù)是先更新到日志之中的,只有commit提交之后,才真正再從日志中更新到mysql表中。你不用去糾結(jié)為什么能讀到它。你只需知道,是事務(wù)與事務(wù)并發(fā)進行時,是具有影響性的,這種影響性的大小被稱為隔離級別。那怎么防止未提交讀呢?就是加寫鎖,然后提交之后釋放鎖,在這個時候,mysql的隔離級別就變成了已提交讀。而加鎖,釋放鎖是由mysql自動完成的,你無需關(guān)心。所以,其實本質(zhì)上是鎖的應(yīng)用,最終導(dǎo)致了不同的隔離級別,不同的隔離級別,鎖的應(yīng)用也不同。
“數(shù)據(jù)未提交,那數(shù)據(jù)庫應(yīng)該沒有改變”,這個假設(shè)其實是錯誤的。數(shù)據(jù)庫的底層設(shè)計都使用了WAL(Write-ahead**Logging)思想,只不過數(shù)據(jù)庫的事務(wù)隔離技術(shù)了提供了各種方案,一個數(shù)據(jù)庫請求即使事務(wù)沒有提交也會發(fā)生數(shù)據(jù)庫內(nèi)部數(shù)據(jù)的變更,有各種技術(shù),像Mysql InnoDB MVCC,只不過是通過一些字段進行控制。
在數(shù)據(jù)庫沒有提交數(shù)據(jù)的時候,你更新的數(shù)據(jù)是在緩存進行更新的,事務(wù)與事務(wù)在并發(fā)進行的時候就叫作隔離級別,只有在提交之后,數(shù)據(jù)才從日志中把數(shù)據(jù)更新到數(shù)據(jù)庫里面。
目前主流的關(guān)系型數(shù)據(jù)庫例如mysql、Oracle都是基于文件系統(tǒng)進行數(shù)據(jù)存儲的,即數(shù)據(jù)是持久化到文件系統(tǒng)的,但基于文件系統(tǒng)的隨機IO讀寫是非常慢的,故數(shù)據(jù)庫都會引入內(nèi)存池,完成對磁盤數(shù)據(jù)的緩存,提高讀寫性能。內(nèi)存池是對所有線程共享的,也就是對所有的數(shù)據(jù)庫事務(wù)是共享的,所謂的未提交,指的是事務(wù)未提交,但此時數(shù)據(jù)已經(jīng)存儲到了共享內(nèi)存中,數(shù)據(jù)已經(jīng)進入到了數(shù)據(jù)庫服務(wù)器中,所以是可見的。
延伸閱讀:
二、MongoDB是什么
非關(guān)系型數(shù)據(jù)庫(nosql ),屬于文檔型數(shù)據(jù)庫。MongoDB采用類JSON的documents來存儲數(shù)據(jù)。數(shù)據(jù)結(jié)構(gòu)由鍵值(key=>value)對組成。
MongoDB采用動態(tài)數(shù)據(jù)模型schema,這意味著不需要預(yù)先定義表的數(shù)據(jù)類型和字段名。當(dāng)MongoDB需要更新文檔documents的時候,可以輕松增加新的字段名或者刪除舊的字段。MongoDB讓數(shù)據(jù)結(jié)構(gòu)更加層級化,因而存儲數(shù)組等復(fù)雜數(shù)據(jù)結(jié)構(gòu)。 在同一個集合collection中,文檔document對字段也沒有強約束,因此更容易設(shè)計差異化的數(shù)據(jù)結(jié)構(gòu)。