Linux下tmpfs與ramfs的對比分析
最近看到一篇文章介紹說用記憶體做MySQL的tmpdir能解決MySQL在使用磁碟臨時表效能低的棘手問題,作者建議用tmpfs(常見的還有ramfs)。首先我覺覺得這個想法不錯,但是侷限性比較大,因為線上總會有些操作需要建立很大的臨時表(雖然這樣的次數可能不多),如果做一個很大記憶體的tmpfs那麼顯然浪費記憶體,如果做一個較小記憶體的tmpfs那麼對於需要建大臨時表的的操作會因為磁碟空間不夠失敗(比如alter table, insert into select 等等),比如如下錯誤:
mysql> insert into test select null, b+1, c, d+2 from test;
ERROR 126 (HY000): Incorrect key file for table '/home/ddb/zbs/ramdisk/tmpdir/#sql_6722_0.MYI'; try to repair it
所以實際環境中最好還是多對錶結構、SQL query做優化儘量避免這些需要建臨時表的操作,另外也可根據實際情況來調整這兩個引數:tmp_table_size,max_heap_table_size,具體使用方法查查官方手冊,關於tmpfs做tmpdir的缺陷參考這篇文章。
接下來說今天的重點Linux下tmpfs與ramfs的異同。
ramfs是Linux下一種基於RAM做儲存的檔案系統。在使用過程中你就可以把ramfs理解為在普通的HDD上建立了一個檔案系統,而現在HDD被替換成了RAM,因為是RAM做儲存所以會有很高的儲存效率。由於ramfs的實現就相當於把RAM作為最後一層的儲存,所以在ramfs中不會使用swap。你什麼時候聽過會把HDD上的檔案swap到哪裡去嗎?平常說的swap都是針對記憶體來說的,而ramfs底層的儲存是RAM,雖然不是HDD,但是在Linux看來它就跟HDD一樣。但是ramfs有一個很大的缺陷就是它會吃光系統所有的記憶體,即使你mount的時候指定了大小,同時它也只能被root使用者訪問。測試方法很簡單:
sudo mount -t ramfs -o size=10M ramfs ./ramfs/
sudo dd if=/dev/zero of=./ramfs/test.file bs=1M count=20
測試時你會發現上面這個操作是能成功的,或者你再自己虛擬機器上乾脆做狠點,直接寫一個比記憶體更大的檔案,你會發現瞬間系統就卡主了。另外在dd命令如果不以root使用者執行就會許可權不夠:
dd: opening `./ramfs/test.file': Permission denied
tmpfs也是Linux下的一個檔案系統,但是它是用vm(virtual memory)實現,umount tmpfs後所有的資料也會丟失,tmpfs就是ramfs的衍生品。tmpfs使用vm實現,因此它會進行swap。但是它有一個相比ramfs的好處:mount時指定的size引數是起作用的,這樣就能保證系統的安全,而不是像ramfs那樣,一不留心因為寫入資料太大吃光系統所有記憶體導致系統被hang住。在我文章最開始的那個例子中就是mount了一個10M大小的tmpfs,然後執行sql 命令(它需要建立的臨時表大於10M),因為tmpfs限制了大小,因此也就報錯。那麼tmpfs適用的場景有哪些呢?在官方文件上主要有如下幾點:
- kernel 內部需要用到它,而我們是無法看到的
- glibc 2.2以上的版本,必須有一個tmpfs被mount在/dev/shm用做POSIX shared memory
- 還有很多包括現在還不知道的用途
- ramfs會因為資料的寫入自動增長空間,所以可能導致最後系統所有的記憶體耗完
- tmpfs可以再mount時限定大小,不會自動增長
- ramfs不會用swap
- tmpfs會使用swap
- 兩者都是用來提升效率,但是tmpfs比ramfs的效能更好。