<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      eaglet

      本博專注于基于微軟技術的搜索相關技術
        博客園  :: 首頁  :: 新隨筆  :: 聯系 :: 訂閱 訂閱  :: 管理

      文件是否真的寫入了磁盤?

      Posted on 2012-09-13 10:48  eaglet  閱讀(10609)  評論(24)    收藏  舉報

      作者:eaglet

      引用請注明出處

       

      寫文件后調用 FileStream.Close; FileStream.Flush; 或者 using (FileStream fs = new FileStream(…)) {} ,文件是否被實際寫入了磁盤?可能大多數人都會說肯定會寫入磁盤,但我要告訴你,不一定!

       

      背景

      我所在的公司有上千臺的計算機在同時運行我們的系統,在實際運行過程中,我們發現有時候我們寫入的文件會出現全0或者部分全0的情況,但程序中可以肯定的是我們已經關閉了文件句柄。這個問題困擾了我很久。它的發生概率大概在幾千分之一,而且大部分是出現在機器重啟時,也就是我們更新軟件后要求機器自動重啟,結果起來后發現更新的軟件中有部分文件的大小是對的,但數據全是0。

      問題分析

      首先考慮的是不是程序的bug,但分析下來,程序沒有任何問題,我們甚至用了 File.WriteAllBytes 這樣的靜態函數來寫文件,依然會出現這個問題。

      其次考慮的是不是磁盤緩存造成?因為windows操作系統每個磁盤上都可以設置 Enable write caching on the device. 如果打開這個開關,寫入操作將先寫入磁盤的緩存,然后在到達大小或時間門限時才寫入物理磁盤。如果內容還沒有完全寫入磁盤就重啟計算機,就會造成數據丟失。設置如下圖所示:

       

      image

       

      于是把這個功能取消,結果發現問題依舊。

      這到底是怎么回事?

      放狗搜索后發現 windows 除了在磁盤的硬件級別上可以提供緩存外,在操作系統層面也有一個文件緩存

      這個功能叫  File Caching, 是 windows 2000 以后提供的功能。如下圖所示:

       

      File data caching process

       

      當進程寫磁盤時,文件會根據一定的策略緩存到系統的文件緩存中,達到一定門限后才會寫入物理磁盤。由于這個系統文件緩存對應用程序是透明的,我們在應用程序中調用 文件的 Close, Flush 只能保證文件已經被寫入了操作系統的文件緩存,但無法保證文件實際被寫入了磁盤。這個機制雖然提供了較好的寫入性能,但卻增加了丟失數據的風險。從應用角度,我們從邏輯上認為寫入已經成功,但實際上并沒有寫入到實際的磁盤,也就是說寫入是否真的成功了,軟件無從知道,這樣帶來很多邏輯上的混亂。特別是一些服務進程利用文件鎖來控制多個進程鎖定的,比如 lucene.net, mongodb 等,就經常出現重啟后文件鎖鎖定出問題的情況,估計也和這個機制的作用有關。

       

      那么這個機制的優點到底在哪里呢?

      微軟提供這個機制當然是有原因的,他的最大優點是大大提高了讀取的性能。我們可以做如下的實驗:

      當我們打開一個大文件,并順序讀取這個文件,我們發現系統開機后,第一次讀取的速度是非常慢的,這個速度主要取決于磁盤的讀取速度,因為第一次讀取是沒有緩存的。但當我們關閉進程,再重新運行進程讀取這個大文件時,無論是順序讀取還是隨機讀取,都比原來快上百倍,這就是因為這個操作系統緩存在里面起了作用,數據是從內存讀取的。由于這個緩存是全局的,進程退出后,文件的緩存并沒有被清空。我所做的開源全文索引項目 HubbleDotNet  的較新版本就充分利用了這個機制,大大提高了機器重啟后首次讀取索引的速度。

      關于windows操作系統的文件緩存機制以及如何優化不在本文的討論范圍內,我將在以后的文章中專門來講述這個機制是如何工作的。

      解決方案

      那么回到這個問題

      我們有沒有辦法關閉這個文件緩存呢?答案是否定的。但幸運的是 windows 為應用提供了一個標志叫 FILE_FLAG_WRITE_THROUGH, 這個標志可以讓應用在寫入緩存的同時直接寫入磁盤。

      用 C# 實現的代碼如下:

      using (System.IO.FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None,
                      8192, FileOptions.WriteThrough))

       

      在程序中做了如上更改后,2000多臺機器運行了半年,沒有發現一次文件數據丟失的問題(原來幾乎每個月會出現幾次),基本可以證明這個機制有效。

      深入問題:

      1. 采用 WriteThrough 后沒有關閉磁盤緩存,會不會造成數據丟失?

      我們再看一下本文最上面的那個圖,磁盤緩存有兩個 CheckBox, 第一個是是否打開磁盤緩存,第二個是是否關閉windows 的文件寫緩存刷新磁盤。如果第二個選中,則有可能會出現數據丟失,如果沒有選中則不會。

      默認設置,這個地方是不選中的。從實際測試來看,磁盤緩存也確實不影響數據丟失的問題。

      2. 采用 WriteThrough 后是否會降低寫入磁盤的性能。

      我認為如果是隨機寫,可能是會有影響的,但如果是順序寫,FileStream 這個類已經提供了緩存功能,并不會有太大的影響。除非你直接調用windows 的文件API去寫入文件并且每次寫入文件的內容都較小,這時確實會有影響。因為每次寫入都會觸發一次物理的磁盤寫。

      主站蜘蛛池模板: 天天综合色一区二区三区| 亚洲精品中文av在线| 麻豆一区二区三区香蕉视频 | 国精产品999国精产| 国产伦精品一区二区三区| 房产| 中文字幕亚洲资源网久久| 40岁大乳的熟妇在线观看| 国产精品日日摸夜夜添夜夜添无码| 亚洲熟女乱色综合亚洲图片| 人人妻人人澡人人爽欧美一区双| 91亚洲国产成人久久蜜臀| 99精品偷自拍| 国产日韩av一区二区在线| 69人妻精品中文字幕| 亚洲精品麻豆一二三区| 亚洲色av天天天天天天| 国产97人人超碰CAO蜜芽PROM| 一道本AV免费不卡播放| 在线高清理伦片a| 欧美白人最猛性xxxxx| 性欧美老人牲交xxxxx视频| 国产一区二区三区18禁| 国产精品日日摸夜夜添夜夜添2021| 91中文字幕在线一区| 亚洲sm另类一区二区三区| 久久97人人超人人超碰超国产| 国产精品毛片无遮挡高清| 97久久精品人人做人人爽| 亚洲av综合色区无码专区| 国产AV影片麻豆精品传媒| 国产精品无遮挡又爽又黄| 久久男人av资源站| 国产亚洲一区二区三区av| 中文字幕有码无码AV| 德安县| 丰满人妻被黑人猛烈进入| 国产丝袜视频一区二区三区 | 国产精品亚洲一区二区在| 免费午夜无码片在线观看影院| 91精品国产午夜福利|