Trim指令

**Trim 命令**（ATA 命令集中稱為 **TRIM**，SCSI 命令集中稱為 **UNMAP**），它使作業系統能通知固態硬碟（SSD）哪些資料塊已不再考慮使用，可以被內部擦除。

Trim 命令幾乎是與 SSD 同時推出的。這是因為 SSD 的底層操作方式與傳統機械硬碟有著顯著不同，若作業系統沿用傳統方法處理諸如刪除和格式化等操作，會導致 SSD 的寫入效能發生下降。Trim（意為修整、修剪、裁剪）使 SSD 能更有效地完成垃圾收集的工作，而不用犧牲對儲存塊的寫入速度。

儘管在引入 Trim 命令前，有些工具（比如「Reset」命令）已經可以將驅動器「重設」為空狀態，但這些操作會刪除驅動器上的所有資料，因而無法用於持續性最佳化。許多 SSD 擁有廠商自己的後台垃圾收集機制，這些工具和 Trim 命令互相獨立，使不支援 Trim 命令的作業系統能完成與之類似的工作，卻依然存在寫入放大的現象，往往也會導致儲存塊壽命過早地衰減。

## 快閃記憶體磁碟機特有的問題

因為許多檔案系統以標記資料塊為「未使用」來處理刪除操作，而非真正「清空」資料，因此儲存媒介（傳統硬碟、SSD）通常不知道哪個磁區 / 頁是正在使用，哪些可被認作空閒空間，這與重寫（rewrite）操作不同，刪除操作不涉及對資料所在磁區 / 頁的物理寫入。SSD 等儲存媒介通常不負責管理檔案系統（例如未使用的資料塊 / 磁區表），也無法獲知哪些資料塊 / 磁區已經可用。這使反刪除工具能通過更底層的方法，從傳統的機械硬碟上恢復檔案，因為儘管作業系統報告使用者檔案已被「刪除」，並騰出了儲存空間。但在儲存媒介上，檔案所在的磁區只有在下一次寫入時，舊資料才會被覆蓋，從儲存媒介的角度看，「刪除」操作更接近於「重寫」。對於機械磁碟來說，這與寫入空磁區沒有區別，但因為 SSD 最底層的一些特性，與將資料寫入空頁相比，重寫會有顯著的開銷，從而潛在地削弱寫入效能。

SSD 在快閃記憶體單元中通常以 4-16kB 為一組來儲存資料（稱之為頁），每 128-512kB 的頁組合成更大的一組（稱之為塊或資料塊）。舉例來說，某一品牌的 SSD 將 4kB 的資料組合成一頁，其資料塊大小是 512kB，每一資料塊包含 128 個頁。NAND 快閃記憶體單元只能在處於空狀態時寫入。如果它們包含資料，則執行寫操作前必須擦除其內容。SSD 一次寫入最少一頁，但由於硬體限制，擦除資料時將會抹除整個資料塊；因此將資料寫入到 SSD 上的空頁時非常快，而寫入已有資料的頁就會明顯變慢。這是因為頁被再次寫入前需要擦除資料，但 SSD 只能擦除一整個資料塊，隨後把資料塊中的其他資料以覆寫的方式（按「讀取、擦除、修改、寫入」的方式）完成；整個塊的內容會先儲存在快取中，然後在 SSD 中擦除整個塊，再將覆寫的頁寫入到快取的塊，最後再將更新的塊寫入快閃記憶體媒介。這種現象也稱寫入放大。

## 操作

TRIM 命令使 SSD 可以從作業系統處得知哪一部分資料將永遠不會被存取。對於刪除操作，作業系統會將整個資料塊標記為可用於新資料，然後向 SSD 傳送 TRIM 命令。SSD 完成這一操作後，在新的資料寫入這一頁時，SSD 將重新整理整個塊的資料，而不保留塊中其他頁原本的內容，從而緩解寫入放大現象（寫入次數更少），並提供更高的寫入吞吐量（不需要執行讀取、擦除、修改），還能顯著延長驅動器壽命。

不同的 SSD 實現的方式有所不同，因此效能可能也有所差異。

TRIM 命令通知 SSD 從 LBA (Logical Block Addressing) 區域上標記為無效，從邏輯層上對該區域進行讀取將不會返回有效資料。從實體層面看，資料仍可能短時間駐留在快閃記憶體內部，SSD 徹底完成垃圾回收的工作之後，恢復資料幾乎是不可能的；這不同於機械硬碟中被刪除的資料可能被資料恢復。

## 實現

### 作業系統支援

Trim 僅在支援它的作業系統上有效。下表列出了各個重要的作業系統支援該命令的首個版本。此外，在 TRIM 命令添加到 ATA 標準之前設計的舊款固態驅動器需要更新韌體（如果有）才能支援 Trim，否則將忽略這個新命令。

### RAID 問題

截至 2017 年 1 月 (2017-01)，大多數基於硬體的 RAID 技術未實現 TRIM 命令的支援。但是，軟體實現的 RAID 通常提供了 TRIM 支援。

Windows：

Windows 10 為 SSD RAID 卷在組態一個 RAID 卷時通過「最佳化驅動器」選項提供了 TRIM 支援。

Mac OS：

macOS RAID 驅動程式不支援 TRIM。自 Mac OS X 10.7 至 macOS 10.12.x 的所有版本均是如此。

對於使用第三方 SoftRAID® 應用程式的 RAID（0,1,4,5 和 10）卷支援 TRIM，包括使用非蘋果品牌 SSD 裝置的 TRIM 支援。
（註：非蘋果品牌的 SSD 裝置必須使用終端命令「sudo trimforce enable」來啟動 TRIM）

Linux：

2011 年 1 月以後的 Linux 核心中 dmraid 的發布版本已實現 BIOS 輔助的「假硬體 RAID」支援，並且現在通行來自 RAID 陣列上的檔案系統的任何 TRIM 請求。

 
不同於 dmraid，Linux 的常規目的軟體 RAID 系統 mdraid 有實驗性的基於批次處理（而不是在檔案刪除時即時）的 TRIM，當系統組態為定期在 RAID 1 陣列上的檔案系統上執行 mdtrim 實用工具（包括 ext3 等沒有原生 TRIM 支援的檔案系統）。在 Linux 的稍晚版本（例如 Red Hat Enterprise Linux 6.5 和 beyond）中 mdraid 支援即時、實際傳遞 TRIM 命令，而不是作為一個批次處理作業。

但請注意，紅帽公司建議不要在大多數 RAID 技術的 SSD 上使用軟體 RAID 1、4、5 和 6，因為大多數 RAID 管理實用工具（例如 Linux 的 mdadm）在初始化期間會在裝置上寫入所有塊以確保校驗和（或 RAID 1/10 情況下的驅動器到驅動器驗證）運作正常，而這導致 SSD 認為除備用區域以外的所有塊都在使用中，從而顯著降低效能。

另一方面，Red Hat 推薦在 SSD 上為 LVM RAID 使用 RAID 1 或 RAID 10，因為這些級別支援 TRIM（在 Linux 術語中稱為 "discard"），並且 LVM 實用工具在建立時不會寫入所有塊到 RAID 1 或 RAID 10 卷。

在 2010 年 3 月的一小段時間內，使用者被誤導相信英特爾快速儲存技術（RST）9.6 驅動程式支援 RAID 卷上的 TRIM，但後來英特爾澄清說，TRIM 支援 AHCI 模式和 RAID 模式的 BIOS 設定，但不支援 RAID 卷的驅動器。

截至 2012 年 8 月，英特爾確認，使用快速儲存技術（RST）11.2 驅動程式的 7 系列晶片組支援微軟 Windows 7 中的 RAID 0 的 TRIM。雖然英特爾沒有確認支援 6 系列晶片組，RAID 0 卷上的 TRIM 已展示為在 Z68、P67 和 X79 晶片組上可用，通過由硬體發燒友修改的 RAID 選項 ROM。據推測，缺乏對 6 系列晶片組的官方支援是由於驗證成本或企圖鼓勵消費者升級，而不是出於技術原因。

在使用 X79 晶片組的主機板上需要修改選項 ROM 的例外是製造商添加了 ROM 開關；這需要 RST 和 RST-E ROM 存在於 BIOS/UEFI 內。這允許使用 RST ROM 而不是 RST-E ROM，從而允許 TRIM 工作。英特爾指出，使用與 ROM 版本相同的驅動程式可以實現最佳效能。例如，如果 BIOS/UEFI 具有 11.0.0.0m 選項 ROM，則應使用 11.x 版本的驅動程式。

### 為不支援的作業系統使用

在使用不支援自動 TRIM 的檔案系統時，某些實用工具可以手動傳送 Trim 命令。通常它們將確定哪些塊為空閒，然後將該列表以一系列的 Trim 命令傳遞給驅動器。這些實用程式可從各製造商（例如 Intel、G.Skill）或作為一般實用程式（例如 Linux 的 hdparm 自 v9.17 起，或者如上所述的 mdtrim）。

## 硬體支援

### ATA

TRIM 命令規範已被標準化為 AT Attachment 介面標準的一部分，由國際資訊科技標準委員會（INCITS）的技術委員會 T13 所領導。 TRIM 根據 DATA SET MANAGEMENT（資料集管理）命令（操作碼 06h）實現，ACS-2 規範草案。ATA 標準被並列（IDE、PATA）和序列埠（SATA）ATA 硬體所支援。

原版 ATA TRIM 命令的缺點是它被定義為不可排隊命令，因此不能輕鬆地與正常的、排隊的讀和寫操作混合。SATA 3.1 引入了一個排隊的 TRIM 命令來糾正這一點。

ATA IDENTIFY DEVICE 命令返回的 SATA Words 69 和 169 定義了不同類型的 TRIM。

* 非確定性 TRIM：TRIM 後每個對邏輯區塊位址（LBA）的讀取命令可能返回不同的資料。
* 確定性 TRIM（DRAT）：TRIM 後對 LBA 的所有讀取命令都返回相同的資料，或者變為確定的。
* TRIM（RZAT）後確定性讀零：TRIM 後對 LBA 的所有讀取命令都將返回零。

在 SATA 字 105 中有額外資訊，描述驅動器可以在每個資料集管理命令（DATA SET MANAGEMENT）支援最多多少個 512 位元組的資料塊。通常此值預設為 8（或 4kB），但許多驅動器將其減少到 1，以滿足微軟 Windows 硬體要求對 TRIM 的部分 —— 該命令完成時間不應超過 20 ms 或者 8 ms × （LBA 範圍項的數量），且兩者中的較大者應始終小於 600 ms。

各 LBA 範圍被稱為一個 LBA 範圍條目，並由八個位元組表示。 LBA 由 LBA 範圍條目的前 6 個位元組表示，範圍長度是由剩下兩個位元組表示的一個從零開始的計數器。如果兩個位元組組成的範圍長度為零，那麼 LBA 範圍條目應視作填充而丟棄。這意味著以 512 位元組為 TRIM 塊範圍支援的裝置，該最大值為 64 個 32 MB，也就是 2 GB。如果裝置在 SATA 字 105 處設為 8，則它應該能在單個 TRIM（資料集管理）命令中修整 16GB。

### SCSI

SCSI 提供了 UNMAP 命令（TRIM 的完全類比），以及帶有 UNMAP 標誌集的 WRITE SAME 命令（10 和 16 個變數）。

### SD/MMC

多媒體記憶卡和 SD ERASE（CMD38）命令提供了與 ATA TRIM 命令類似的功能，但它要求擦除的塊用 0 或 1 重寫。eMMC 4.5 進一步定義了一個「discard」（丟棄）子操作，從而更緊密的配合 ATA TRIM，因為丟棄的塊的內容可以被認為是不確定的（即「不在乎」的）。

## 缺點

* 在使用加密時，TRIM 命令的相關資訊將揭露哪些塊正在使用，哪些沒有。
* TRIM 命令的原始版本已被 T13 小組委員會定義為非排隊命令，因此執行不當可能造成大量的錯誤執行。例如，如果它在作業系統的每個刪除命令後發出，該命令的非排隊性質將要求驅動程式先等待所有未完成的命令完成，然後發出 TRIM 命令，最後再繼續正常命令。TRIM 可能需要很長時間才能完成，這取決於 SSD 中的韌體，並還可能觸發垃圾收集周期。這種缺陷可以用定期執行批次 TRIM 的解決方案來最小化，而不是在每次檔案刪除時執行修剪，批次處理任務可以在系統利用率最小時排程。這項 TRIM 缺點已在 Serial ATA 修訂 3.1 中解決，其中引入了排隊的 TRIM 命令。
* 排隊的 TRIM 命令已在多款裝置中涉及嚴重的資料損壞，最顯著的是 Micron 的 M500、Crucial 的 M500、以及 Samsung 8\*\* 系列。在 2015 年 7 月 1 日，Linux 作業系統在這些裝置上的資料損壞已得到確認。

這些裝置已被列入 Linux 核心中 libata-core.c 的黑名單，從而強制傳送非排隊的 TRIM 命令到這些裝置，而不是排隊的 TRIM 命令：

* Micron M500，所有韌體版本（僅 MU07 之前有此問題，但 Linux 尚未跟進）
* Crucial M500，所有韌體版本，包括工廠重新認證的 SSD（僅 MU07 之前有此問題，但 Linux 尚未跟進）
* Micron M510，韌體版本 MU01
* Micron M550，韌體版本 MU01
* Crucial M550，韌體版本 MU01
* Crucial MX100，韌體版本 MU01
* 三星 SSD 8\*\* 系列，所有韌體版本

此檔案也已將 SuperSSpeed S238 列入常規 TRIM 的黑名單，因為發出 TRIM 會導致錯誤的塊遺失資料。

libata-core.c 還有一個列出子系統維護者已確認正確實現 DRAT 和 RZAT 標誌（flags）的 SSD，這不同於許多忽略它們的驅動器。白名單中的裝置如下：

* Crucial 多款 SSD
* Intel 多款 SSD（不包括 Intel SSD 510）
* Micron 多款 SSD
* 三星多款 SSD
* 希捷多款 SSD

## 參見

* 資料殘留

## 參考資料

## 外部連結

* _From write() down to flash chips_ – An explanation on how the TRIM command lets SSDs erase data not used by the filesystem
* _TRIM Command White Paper_（頁面存檔備份，存於網際網路檔案館） – A white paper explaining the command's purpose and actions
* Fusion-io Patent "Apparatus, system, and method for redundant write caching"（頁面存檔備份，存於網際網路檔案館）