UPDATE 時，InnoDB 會把新資料寫到表格內，然後把可能會被 rollback 的舊資料放到表格外：
In InnoDB, only the most recent version of an updated row is retained in the table itself. Old versions of updated rows are moved to the rollback segment, while deleted row versions are left in place and marked for future cleanup. Thus, purge must get rid of any deleted rows from the table itself, and clear out any old versions of updated rows from the rollback segment.
DELETE 清除的資料則是由 purge thread 處理：
All the information necessary to find the deleted records that might need to be purged is also written to the rollback segment, so it's quite easy to find the rows that need to be cleaned out; and the old versions of the updated records are all in the rollback segment itself, so those are easy to find, too.
所以可以在 InnoDB 看到 purge thread 相關的設定：「MySQL :: MySQL 5.7 Reference Manual :: 14.6.11 Configuring InnoDB Purge Scheduling」，負責處理這些東西。
而在 PostgreSQL 的作法則是反過來，舊的資料放在原來地方，新資料另外存：
PostgreSQL takes a completely different approach. There is no rollback tablespace, or anything similar. When a row is updated, the old version is left in place; the new version is simply written into the table along with it.
Lacking a centralized record of what must be purged, PostgreSQL's VACUUM has historically needed to scan the entire table to look for records that might require cleanup.
而在今年 (2018) 的文章裡，EnterpriseDB 就提出了 zheap 的想法，在
UPDATE 時寫到 table 裡，把可能被 rollback 的資料放到 undo log 裡。其實就是把 InnoDB 那套方法拿過來用，只是整篇都沒提到而已 XD：
That brings me to the design which EnterpriseDB is proposing. We are working to build a new table storage format for PostgreSQL, which we’re calling zheap. In a zheap, whenever possible, we handle an UPDATE by moving the old row version to an undo log, and putting the new row version in the place previously occupied by the old one. If the transaction aborts, we retrieve the old row version from undo and put it back in the original location; if a concurrent transaction needs to see the old row version, it can find it in undo. Of course, this doesn’t work when the block is full and the row is getting wider, and there are some other problem cases as well, but it covers many useful cases. In the typical case, therefore, even bulk updates do not force a zheap to grow. Instead, the undo grows. When a transaction commits, all row versions that will become dead are in the undo, not the zheap.
不過馬上就會想到問題，如果要改善問題，不是個找地方記錄哪些位置要回收就好了嗎？順便改變方法是為了避免 fragment 嗎？