--- title: DB淺談-Transaction Processing and Recovery tags: DB description: DB淺談-事務處理與恢復 --- # Transaction Processing and Recovery ## Movitation ```Transction```是指資料庫中一個不可被切分的邏輯工作單元. 允許將多個操作表示為一個步驟. 操作包含了讀取跟寫入修改數據紀錄. Transction必須遵從ACID這四個原則. [Haerder, Theo, and Andreas Reuter. 1983. “Principles of transaction-oriented database recovery.” ACM Computing Surveys 15 no. 4 (December):287–317](https://dl.acm.org/doi/10.1145/289.291) [微服務瞎談(4) 單機ACID事務 & MySQL主從同步](https://ithelp.ithome.com.tw/articles/10235277) 資料庫要完成Transction還需要多個組件一起協同作業, 在節點內部, ```Transaction manager```負責協調、調度與追蹤tx與tx各個步驟. ```Lock manager```保護對資料的訪問, 並防止可能破壞數據完整性的併發存取. ```Page cache```充當了硬碟與存儲引擎中間的媒介. ```Log manager```紀錄了在page cache上的操作. 要完成單機tx操作跑不掉上面組件的協作. 若是分佈式tx, 就需要額外的組件了. [Optimizing InnoDB Transaction Management](https://dev.mysql.com/doc/refman/8.0/en/optimizing-innodb-transaction-management.html) [MySQL · 引擎特性 · 8.0 Lock Manager](http://mysql.taobao.org/monthly/2020/04/09/) [InnoDB Locking](https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html) [MySQL · 性能优化 · PageCache优化管理](http://mysql.taobao.org/monthly/2020/09/01/) [Redo Log](https://dev.mysql.com/doc/refman/8.0/en/innodb-redo-log.html) [MySQL字典](https://dev.mysql.com/doc/refman/8.0/en/glossary.htm) ## Buffer Management 大部分的資料庫都採用two-level memory hierarchy : 慢速的持久化存處(disk)與高速的main memory(Ram). Pages被cached在ram中的話, 直接就能返回其cached copy. 假設沒有其他process修改過數據, 那cached pages就能一直被reuse. 這種作法也能稱為virtual disk [Organization and maintenance of large ordered indexes](https://link.springer.com/article/10.1007/BF00288683) 當ram中沒有cached page時, . 上面這樣的機制稱為```page cache```或```buffer pool``` [MySQL Buffer Pool](https://dev.mysql.com/doc/refman/8.0/en/innodb-buffer-pool.html) [MySQL · 性能优化 · PageCache优化管理](http://mysql.taobao.org/monthly/2020/09/01/) OS其實也有page cache的概念, OS會利用unused memmory來透明地緩存硬碟上的內容, 提供I/O性能. 把硬碟做加載的過程稱為```Page in``` cached page要是被更改就成為```dirty```, 這些dirty會被```flush```到硬碟上. 但暫存區總是會滿的, 因為容量配置上, 就是比硬碟小, 總是會被填滿的, 這時候就必須把某個page直接換出(evict)buffer. ![](https://i.imgur.com/KAiQvjV.png) 圖5.1展示了Btree的表示, 以及cache page與disk page之間的關係. 因為page cache是以亂序載入disk page到記憶體中的空白處, 所以硬碟中與記憶體中的page順序併不存在直接的映射. 都是透過buffer pool來對照的. page cache的主要用途有 - 緩存page到memory中 - 對硬碟上page的修改給緩衝(buffer), 並且修改看到的版本是buffer上的版本 - 被請求的page不再memory中且free space還夠時, page cache機制會將該page給page in, 並返回緩存的版本 - 如果請求的page已經被緩存, 則直接返回緩存的版本 - 如果free space已經不夠來page in新的page, 就會有些page被evict, 被evict的page, 會被flush回disk. ### Cache Eviction 讓memory盡量保持在空間利用度極高的狀態是好事情. 可以讓更多的讀取請求直接從buffer返回. 也能讓同一個page上的修改請求被緩衝再一起, 一起flush寫回disk. 當page cache已經滿了, 為了填充新內容, 就必須要evict舊頁. 如果該cached page跟disk是同步的(表示非dirty), 並且該page沒被pin/referenced, 就可以被立刻evict. dirty page必須在flush完成後才能被evict. 如果該page正在被存取, 也不能被evict. ![](https://i.imgur.com/C7Rx8EY.png) ![](https://i.imgur.com/CTP670H.png) ![](https://i.imgur.com/5Ql3I3a.png) 每次evict就觸發flush to disk, 性能當下會很差. 所以有些資料庫會使用另一個背景進程, 檢查可能被evict的dirty page來更新進disk. [MySQL Purge](https://dev.mysql.com/doc/refman/8.0/en/glossary.html#glos_purge) 刷到disk的重點就是durability(持久性), 如果db crash了, 所有還沒被flush完成的資料將會lost. 所以為了確保都能被完整flush, 會有個checkpoint進程來觸發把WAL跟page cache做flush, 把有log已經flush完成, 才能從WAL中丟棄. 過程都完成了, Dirty page才能被evict出page cache. [MySQL Checkpoint](https://dev.mysql.com/doc/refman/8.0/en/glossary.html#glos_checkpoint) flush strategiec trade-offs - 推遲(postpone)flushes來減少disk access次數 - 提早(preeptively)fluss page來能快速地eviction - 挑選pages來被evict, 且用最優的順序做flush - 保持cache size在memory的限制內 - 避免資料還沒被持久化到disk時, 就被丟失了 ### Locking Pages in Cache 併發得讀取可能去請求同一個page, 併發的寫入也是.