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，否則將忽略這個新命令。

作業系統｜支持始自｜備註

DragonFly BSD｜2011-052011年5月

FreeBSD｜2010-078.1 - 2010年7月｜在8.1中的塊設備層中添加了支持。文件系統支持在FreeBSD 8.3和FreeBSD 9中添加，隨Unix文件系統（UFS）而來。ZFSTrim支持在FreeBSD 9.2中添加。FreeBSD 10支持在軟體RAID上配置Trim。

NetBSD｜2012-102012年10月

Linux｜2008-12-252.6.28–2008年12月25日｜最初在2.6.28中添加了對FTL NAND快閃記憶體設備的discard（丟棄）操作符的支持。對ATA TRIM命令的支持在2.6.33中添加。並非所有文件系統都能使用trim。可以自動發出修剪請求的文件系統有Ext4、Btrfs、FAT、GFS2、JFS和XFS。但是由於性能問題，在受支持SSD上進行定期修剪默認情況下已被禁用。Ext3、NILFS2和OCFS2提供Ioctl來執行離線修剪。TRIM規範稱支持修剪特定範圍列表，但截至內核3.0，修剪僅能較慢地逐個調用單個範圍。

MacOS｜2011-06-2310.6.8–2011年6月23日｜儘管AHCI塊設備驅動程序在10.6.6 (10J3210)中得到了顯示設備是否支持TRIM操作的功能，該功能本身仍不可用，直至10.6.8暴露通過IOStorageFamily執行TRIM操作，以及文件系統（HFS+）的支持。直到10.10.4，Mac OS X只為蘋果品牌的SSD原生啟用TRIM；第三方實用程序可使其適用於其他品牌。舊的第三方TRIM驅動程序在Yosemite更新時已停止工作。現已有更新的適用於OS X Yosemite的驅動程序。在Mac OS X 更新10.10.4中，蘋果公司添加了一個命令行使用工具trimforce，它可以用於為第三方SSD啟用TRIM。

Microsoft Windows｜2009-10Windows 7和Windows Server 2008 R2 - 2009年10月｜Windows 7最初支持的TRIM僅適用於包括ATA和SATA的AT Attachment系列中的驅動器，並不對任何其他包括Storport PCI-Express SSD設備支持此命令，即使即使設備本身將接受該命令。已確認Windows 7上AHCI和舊有IDE/ATA模式下的原生微軟碟機動支持TRIM命令。Windows 8及之後版本的Windows作業系統支持基於NVMe的PCI Express SSD的trim，以及來自SATA的TRIM命令完全模擬的unmap命令，用於使用SCSI驅動程序堆棧的設備。微軟已為Windows 7發布一個 KB2990941更新，這在使用DISM集成到Windows 7安裝程序時增加NVM Express的支持，包括對PCIe SSD設備的TRIM。

OpenSolaris｜2010-072010年7月

Android｜2013-74.3 - 24 July 2013｜每24小時自動運行`fstrim`，僅在設備已空閒至少1小時並且電量80%（如果已連接充電器則30%）時執行。

### RAID問題

大多數基於硬體的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"