linux 同步IO: sync、fsync與fdatasync
傳統的UNIX實現在核心中設有緩衝區快取記憶體或頁面快取記憶體,大多數磁碟I/O都通過緩衝進行。當將資料寫入檔案時,核心通常先將該資料複製到其中一個緩衝區中,如果該緩衝區尚未寫滿,則並不將其排入輸出佇列,而是等待其寫滿或者當核心需要重用該緩衝區以便存放其他磁碟塊資料時,再將該緩衝排入輸出佇列,然後待其到達隊首時,才進行實際的I/O操作。這種輸出方式被稱為延遲寫(delayed write)(Bach [1986]第3章詳細討論了緩衝區快取記憶體)。
延遲寫減少了磁碟讀寫次數,但是卻降低了檔案內容的更新速度,使得欲寫到檔案中的資料在一段時間內並沒有寫到磁碟上。當系統發生故障時,這種延遲可能造成檔案更新內容的丟失。為了保證磁碟上實際檔案系統與緩衝區快取記憶體中內容的一致性,UNIX系統提供了sync、fsync和fdatasync三個函式。
sync函式只是將所有修改過的塊緩衝區排入寫佇列,然後就返回,它並不等待實際寫磁碟操作結束。
通常稱為update的系統守護程式會週期性地(一般每隔30秒)呼叫sync函式。這就保證了定期沖洗核心的塊緩衝區。命令sync(1)也呼叫sync函式。
fsync函式只對由檔案描述符filedes指定的單一檔案起作用,並且等待寫磁碟操作結束,然後返回。fsync可用於資料庫這樣的應用程式,這種應用程式需要確保將修改過的塊立即寫到磁碟上。
fdatasync函式類似於fsync,但它隻影響檔案的資料部分。而除資料外,fsync還會同步更新檔案的屬性。
對於提供事務支援的資料庫,在事務提交時,都要確保事務日誌(包含該事務所有的修改操作以及一個提交記錄)完全寫到硬碟上,才認定事務提交成功並返回給應用層。
一個簡單的問題:在*nix作業系統上,怎樣保證對檔案的更新內容成功持久化到硬碟?
1. write不夠,需要fsync
1 #include <unistd.h>
2 int fsync(int fd);
1 #incude <sys/mman.h>
2 int msync(void *addr, size_t length, int flags)
msync需要指定同步的地址區間,如此細粒度的控制似乎比fsync更加高效(因為應用程式通常知道自己的髒頁位置),但實際上(Linux)kernel中有著十分高效的資料結構,能夠很快地找出檔案的髒頁,使得fsync只會同步檔案的修改內容。
2. fsync的效能問題,與fdatasync
"Unfortunately fsync() will always initialize two write operations : one for the newly written data and another one in order to update the modification time stored in the inode. If the modification time is not a part of the transaction concept fdatasync() can be used to avoid unnecessary inode disk write operations."
多餘的一次IO操作,有多麼昂貴呢?根據Wikipedia的資料,當前硬碟驅動的平均尋道時間(Average seek time)大約是3~15ms,7200RPM硬碟的平均旋轉延遲(Average rotational latency)大約為4ms,因此一次IO操作的耗時大約為10ms左右。這個數字意味著什麼?下文還會提到。
Posix同樣定義了fdatasync,放寬了同步的語義以提高效能:
1 #include <unistd.h>
2 int fdatasync(int fd);
"fdatasync does not flush modified metadata unless that metadata is needed in order to allow a subsequent data retrieval to be corretly handled."
3. 使用fdatasync優化日誌同步
在Berkeley DB下,如果開啟了AUTO_COMMIT(所有獨立的寫操作自動具有事務語義)並使用預設的同步級別(日誌完全同步到硬碟才返回),寫一條記錄的耗時大約為5~10ms級別,基本和一次IO操作(10ms)的耗時相同。
1.每個log檔案固定為10MB大小,從1開始編號,名稱格式為“log.%010d"2.每次log檔案建立時,先寫檔案的最後1個page,將log檔案擴充套件為10MB大小3.向log檔案中追加記錄時,由於檔案的尺寸不發生變化,使用fdatasync可以大大優化寫log的效率4.如果一個log檔案寫滿了,則新建一個log檔案,也只有一次同步metadata的開銷
相關文章
- 3.13 sync、fsync和fdatasync函式函式
- 【轉】linux非同步io機制Linux非同步
- IO模式和IO多路複用(阻塞IO、非阻塞IO、同步IO、非同步IO等概念)模式非同步
- Linux上Oracle啟用非同步IOLinuxOracle非同步
- 非同步IO,同步IO,Direct IO,FILESYSTEMIO_OPTIONS, DISK_ASYNCH_IO [final]非同步
- Windows核心程式設計:第10章 同步裝置IO與非同步裝置IOWindows程式設計非同步
- 深入理解Fsync
- 非同步IO非同步
- Oracle在Linux下使用非同步IO配置OracleLinux非同步
- 如何解讀 Java IO、NIO 中的同步阻塞與同步非阻塞?Java
- 【轉載】Linux上Oracle啟用非同步IOLinuxOracle非同步
- asyncio(非同步io)非同步
- ORACLE 非同步IOOracle非同步
- Linux之檔案系統的開機掛載 async/sync 非同步/同步 等【轉】Linux非同步
- Using V$BACKUP_ASYNC_IO / V$BACKUP_SYNC_IO to Monitor RMAN PerformanceORM
- Java 非阻塞 IO 和非同步 IOJava非同步
- 檔案讀寫網路IO簡單瞭解,同步IO和非同步IO非同步
- python非同步IO與批量請求處理Python非同步
- Oracle在Linux下使用非同步IO(aio)配置(轉)OracleLinux非同步AI
- Linux上Oracle是否使用非同步io的診斷LinuxOracle非同步
- 轉:SYBASE在Linux下使用非同步IO(aio)配置Linux非同步AI
- Linux的非同步IO(AIO)在Oracle中應用Linux非同步AIOracle
- 5 Using Far Sync Instances 使用Far Sync遠端同步例項
- java同步非阻塞IOJava
- Linux SYNC-fsLinux
- log file sync(日誌檔案同步) 與 Log file parallel write 等待事件Parallel事件
- .NET非同步程式設計:IO完成埠與BeginRead非同步程式設計
- VSCode 使用Settings Sync同步配置VSCode
- BitTorrent Sync 基於BT的檔案同步
- Oracle 之 AIO (非同步io)OracleAI非同步
- PostgreSQL非同步IO實測SQL非同步
- 基於linux原生非同步io建立的簡易聊天程式Linux非同步
- IO - 同步 非同步 阻塞 非阻塞的區別非同步
- 談談對不同I/O模型的理解 (阻塞/非阻塞IO,同步/非同步IO)模型非同步
- laravel sync()同步時修改中間表欄位Laravel
- 【PWA學習與實踐】(8)使用Service Worker進行後臺同步 – Background Sync
- 【PWA學習與實踐】(8)使用Service Worker進行後臺同步 - Background Sync
- 華碩AURA SYNC神光同步教程 AURA神光同步是什麼意思?