2015年1月14日水曜日

Windowのファイル更新日時(前編) ファイルを別のドライブに置いたら更新日時が変わった?

こんにちは。近藤です。



以前、Windowsサーバ環境で、ファイルが更新されたら(ファイルの更新日時を監視)トリガを実行する、という運用をしているお客様から、「トリガが監視対象としているファイルを、トリガの監視フォルダに配置するのと同時に別ドライブにもバックアップを置いている。トリガ実行後に、監視対象としているファイルを、ファイル作成環境から監視フォルダに残っている、既にトリガ実行されたファイルに上書きしても、同一ファイルなのでトリガは実行されない。しかし、トリガ実行されたファイルと同一であるバックアップファイルをトリガの監視フォルダに上書きすると、トリガが実行されてしまう場合がある。」という話が来ました。
同じファイルなのに、なぜバックアップ環境から持ってきたファイルではトリガが実行されてしまったのでしょうか?そして、なぜ常に実行されるわけでは無く、「実行される場合がある」だったのでしょうか?

発生する条件:

「おおもとのファイルは同一」なので、ファイルの内容は一致。ということは、「更新日時」が異なる状態になっていることが想像できます。普通は、上記に書いてあるようなファイルコピーでは更新日時は変わりません。
ですが、ある条件のとき、更新日時が変わってしまいます。その条件とは、
「異なるファイルシステム間でのファイルコピー」
です。

ファイルシステム?:

ファイルシステムとは、簡単に説明すると、ファイルなどのデータを管理する方式です。
現在のWindowsでは、以下のファイルシステムを使用することができます。
(OSや適用しているサービスパックによっては、利用できないファイルシステムも存在します)

  • NTFS
    Windows NT系の標準ファイルシステムで、大容量対応や堅牢性、耐障害性、セキュリティなどが特徴です。
  • FAT(FAT16)
    OSのファイルシステムとしては、DOSやWindows 9xの頃まで標準のファイルシステムとして用いられていました。構造が簡単なので、SD / miniSD / microSDカードや4GBまでのUSBメモリなど、外部ストレージで用いられています。今でも、投げ売りされていたり家に転がっていたりする4GB以下のUSBメモリや、デジカメや携帯・スマホで使用しているSD / microSDカードで見かけます。
  • FAT32
    32ビット化されたFATです。Windowsでは、Windows 95 OSR2から使用可能になりました。構造が簡単で、各種OSからも読み書きすることができるため、データ受け渡し用途や、SDHC / miniSDHC(私は見たことがありませんが…) / microSDHCカードやUSBメモリなど、外部ストレージやフラッシュストレージでも用いられています。
    Windowsでは、2TBまでのFAT32を認識することができます。しかし、Windows NT系では、作成(フォーマット)するときの最大領域サイズが、32GBに制限されています(Windows 9x系では、この制限はありませんでした)。
  • exFAT
    FAT32よりも大きな領域、ファイルを扱えるようにしたものです。構造が簡単なので、現在はSDXC / microSDXCカードなど、大容量フラッシュストレージで用いられています。ですが、読み書きできるOSが少ないので、データ受け渡し用途としてはあまり使われていません。Windowsの「フォーマット」では、最小領域サイズが32GBに制限されています。ですので、作成(フォーマット)する領域が32GBより大きいときにexFATフォーマットを行うことができ、作成(フォーマット)する領域が32GB以下のときにFAT32フォーマットを行うことができます。
  • ReFS
    Windows Server 2012で新たに導入されたファイルシステムです。ですが、システムドライブでは使用することができなかったりするので、使ったことのあるかたは少ないのではないでしょうか?


ファイルシステムごとのタイムスタンプ:

ここでは、比較するために、タイムスタンプは「作成」「更新」「アクセス」のみ記載しています。

  • NTFS
    • 作成日時 100ナノ秒単位
    • 更新日時 100ナノ秒単位
    • アクセス日時 100ナノ秒単位(分解能は1時間単位)
    • タイムスタンプの持ち方:UTC
  • ReFS
    • 作成日時 100ナノ秒単位
    • 更新日時 100ナノ秒単位
    • アクセス日時 100ナノ秒単位
    • タイムスタンプの持ち方:UTC
  • FAT (FAT16)
    • 作成日時 10ミリ秒単位
    • 更新日時 2秒単位
    • アクセス日時 1日単位(=アクセス日付)
    • タイムスタンプの持ち方:ローカルタイム
  • FAT32
    • 作成日時 10ミリ秒単位
    • 更新日時 2秒単位
    • アクセス日時 1日単位(=アクセス日付)
    • タイムスタンプの持ち方:ローカルタイム
  • exFAT
    • 作成日時 10ミリ秒単位
    • 更新日時 10ミリ秒単位
    • アクセス日時 2秒単位
    • タイムスタンプの持ち方:ローカルタイム、UTC(Windows Vista SP2から)

このように、ファイルシステムによって、保持されているタイムスタンプの単位が異なります。そして、1秒以下の値で記録されているファイルシステムでも、プログラムで更新日時を取得するとDateTime型、つまり1秒単位の値が取得されてきます。

何が起きたのか?:

はじめの話に戻り、この例では何が起きていたのかというと、
「異なるファイルシステム間でのファイルコピー」
と書いたとおり、

  • 監視ファイルを作成した環境および監視フォルダのある環境のファイルシステムはNTFS
    (=更新日時は、100ナノ秒単位で記録)
  • バックアップした環境のファイルシステムはFAT32
    (=更新日時は、2秒単位で記録)

となっていたことが原因でした。
例を用いて説明すると、
トリガファイル作成時のファイルを“A.txt”とします。
“A.txt”が、NTFS上で
 2015/01/13 10:10:59.0000
に更新されたとすると、このファイルの更新日時には
 2015/01/13 10:10:59.0000
が設定されます。
このファイルをNTFSにコピーしても、更新日時は
 2015/01/13 10:10:59.0000
のまま変わりません。
しかし、このファイルをFAT32にコピーすると、更新日時は2秒単位(偶数秒)にしか持つことができないので、FAT / FAT32が扱うことのできる、最も近い未来日時である
 2015/01/13 10:11:00
となってしまいます。
このFAT32のファイルをNTFSに持ってくると、
 2015/01/13 10:11:00.0000
となります。
NTFSで作成したファイルそのものの更新日時をプログラムで取得すると、
 2015/01/13 10:10:59
となりますが、FAT32から持ってきたファイルの更新日時をプログラムで取得すると、
 2015/01/13 10:11:00
となります。
このように、ファイルのコピーだけで、更新日時が1秒進んでしまいました。
その結果、「ファイルが更新された」と判断されてしまった、ということです。

なお:

robocopyコマンド(Windowsに付属している、堅牢性が高くリッチなファイルコピーコマンド)では、これに対応するために「/FFT」オプション(ファイルの新旧をFATファイル時間で判定するオプション)があります。このオプションを使用すると、NTFSの更新日時(2015/01/13 10:10:59)とFATの更新日時(2015/01/13 10:11:00)を同じ時間として判定するようになり、更新ファイルのみを上書きコピーすることができます。

次回:

今回は、コピーによってファイルの更新日時自体が変わってしまった例を取り上げしました。
次回は、この更新日時が変わってしまったファイル同士を、Windowsエクスプローラーがどう処理するか(実は、Windows OSによって動作が異なるのです)と、「更新日時」が変わっていないのに、違う更新日時に見えてしまう例を書きたいと思います。


0 件のコメント:

コメントを投稿