MySQLが稼働中のサーバーで、何らかの要因でサーバー内のシステム時計が狂い過去の時間になってしまった場合、MySQLではtimestamp型など、どのような挙動になるのでしょうか?


また、もし過去の時間になってしまった場合、MySQL側で対処しデータを保存しないようにしたいのですが、その方法もあれば教えて下さい。

よろしくお願い致します。

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2013/11/24 18:12:23
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:JULY No.1

回答回数966ベストアンサー獲得回数247

ポイント34pt

既に保存されているデータには何ら影響はありません。

ただ、処理の中で CURRENT_TIMESTAMP や now() を使ってデータを挿入、更新しているところがあると、timestamp 型のカラムでソートした時に期待した順序ではなくなったり、unique 制約がある timestamp 型のカラムで、現在時刻と全く同じ値を持つレコードが存在すると、レコードの挿入に失敗する、という事はあるかもしれません。

MySQL 自体は、あくまでも、言われたとおりにデータを保存しているだけなので、timestamp 型に過去の時刻でも未来の時刻でも入れる事はできます。MySQL に保存されているデータが突然、別なデータに変わる事はありません。問題があるとすれば、そのデータを扱うアプリケーション側の問題です。

時計を過去に戻した瞬間に、MySQL 側の動作自体に無いか影響が無いか、という事は考えたのですが、具体的に、こんな問題が起こる、という話は見つけられませんでした。1年ほど前に、うるう秒の問題で MySQL がストールする現象が発生(原因は、Linux カーネル側の問題)した事はありますが、通常は問題ないはずです。

id:wankodon

なるほど。素直な実装なのですね。アプリ側でチェックすることにします。
回答有り難うございました。

2013/11/20 05:31:07

その他の回答2件)

id:JULY No.1

回答回数966ベストアンサー獲得回数247ここでベストアンサー

ポイント34pt

既に保存されているデータには何ら影響はありません。

ただ、処理の中で CURRENT_TIMESTAMP や now() を使ってデータを挿入、更新しているところがあると、timestamp 型のカラムでソートした時に期待した順序ではなくなったり、unique 制約がある timestamp 型のカラムで、現在時刻と全く同じ値を持つレコードが存在すると、レコードの挿入に失敗する、という事はあるかもしれません。

MySQL 自体は、あくまでも、言われたとおりにデータを保存しているだけなので、timestamp 型に過去の時刻でも未来の時刻でも入れる事はできます。MySQL に保存されているデータが突然、別なデータに変わる事はありません。問題があるとすれば、そのデータを扱うアプリケーション側の問題です。

時計を過去に戻した瞬間に、MySQL 側の動作自体に無いか影響が無いか、という事は考えたのですが、具体的に、こんな問題が起こる、という話は見つけられませんでした。1年ほど前に、うるう秒の問題で MySQL がストールする現象が発生(原因は、Linux カーネル側の問題)した事はありますが、通常は問題ないはずです。

id:wankodon

なるほど。素直な実装なのですね。アプリ側でチェックすることにします。
回答有り難うございました。

2013/11/20 05:31:07
id:Sampo No.2

回答回数556ベストアンサー獲得回数104

ポイント33pt

実際の時間順と記録上の時間順が入れ替わってしまわないかという問題についてご心配でしょうか?

結論から言うと心配する必要はありません。

  • 狂うときは、徐々に進んでいくか徐々に遅れていくかですよね。このときは、時間のずれが発生しているとは言え、時間順の狂いは発生していません。
  • 狂いを直すときです。UNIXでもWindowsでも、サーバ用のOSは時間を直すとき、徐々に遅らすか徐々に進ます方法で時刻を修正します。ですので時間順の狂いは発生しないようになっています。

というわけで、時計に狂いのある状態では危険だからデータを保存しない、などのような判断をする必要はないようになっています。

id:wankodon

通常ありえないことですが、ユーザーが手動で時刻を設定してしまった等のオペーレションミスも想定していました。
回答有り難うございます。

2013/11/20 05:34:19
id:language_and_engineering No.3

回答回数170ベストアンサー獲得回数63

ポイント33pt

>何らかの要因でサーバー内のシステム時計が狂い過去の時間になってしまった場合

このような自体がそもそも発生してはいけません。
なので,時刻情報が重要なサーバには,時刻が狂わないようにntpデーモンを必ず入れておきます。
これで問題となる状況自体を回避できます。


>timestamp型など、どのような挙動になるのでしょうか
C:狂った時間で時刻が記録されます。
R:狂う前の時間が読み取られます。
U:狂った時刻で時刻が更新されます。
D:普通に削除されます。


>もし過去の時間になってしまった場合、MySQL側で対処しデータを保存しないようにしたい

上述の通り,OS側ではNTPサーバとの通信によって時刻の正当性を担保します。

DB側で時刻の正当性を担保したい場合,
既存レコードの中から最新の一件の情報をSELECTして,そこに記録されている時刻を見るという手があります。
もしその時刻が未来だったら,ありえないレコードなわけで,システム時刻が狂って過去にさかのぼっていると判断できます。
また,一定間隔でテーブル内にレコードが記録されるとしたら,それらのレコードの記録時刻の間隔をチェックしてみるというのも一つの手です。間隔が通常値でなければ,その時点でシステム時刻は狂ったのだと判断できます。
でも,これらの手法はあんまり良い手ではありません。

いずれにしても,DBはOS上で動く単なるアプリであり,
システム時刻を管理しているのはOSですから,
DBではなくOS側で別個に時刻の狂いを防御する機構を設けないといけません。

他1件のコメントを見る
id:language_and_engineering

こう考えて下さい。


私たち人間は,いま時間が止まったかどうかを認識することはできません。

いま時間が巻き戻ったかどうかに,自力で気づくこともできません。

時間が知らないうちに進んでいたかどうかも,人間の感覚ではよく察知できません。気づけないのです。普通に生活し続けてしまうでしょう。

だから,人間の感覚は,「時刻の狂い」を検出することは不可能なのです。
与えられた時刻の上で,それを前提として生きて存在しているからです。


ただし,もしもある瞬間に人間が時計を見て,時刻を記憶できたとしましょう。
そして次の瞬間に時計を見たときに時計の針が巻き戻っていて,先ほどの記憶も脳の中に残っており,両者の情報を比較することができたとしましょう。

それを人間の脳ができた場合,外部の情報や過去の記憶の蓄積に頼ったおかげで,ようやく「時間が巻き戻っている」事に気づくのです。

人間の脳だけでは時刻の狂いを察知できませんが,外部情報とその「軌跡(時刻が定期的に残した情報の痕跡と道のり)」を認識・分析することによって,時刻の狂いを推察することは可能になりうる,というわけです。


同様に,アプリも人間の脳のようなものです。
自力では時刻の狂いなど検出できません。
できるのは,自分が過去から持っている記憶と照らし合わせることだけです。
そうすれば,変なことが起きていないか最低限のチェックをすることはできます。


したがって・・・
>アプリ側でも時刻のチェックを行うようにします
ではなく,
>アプリ側でも時刻の整合性のチェックを行うようにします
となりますね。

アプリ側で時刻の狂いを認識しようとしても直接は無理なので,システム要件として成立しません。
できるのは,時刻の整合性をベストエフォートでチェックすることなのです。

金融システムなど,よっぽどミッションクリティカルなシステムでは,こういう整合性のチェック処理も実装しますね。


アプリ側で時刻のずれ(例えば,誰かがオペミスで手動で時刻を変更したかどうか)を検出したい場合,一番厳重な方法があります。

毎秒,DB内に「時刻証跡」レコードを投入し,現在時刻を毎秒ごとに記録させ,蓄積させるのです。(RDBではなくファイルシステム上で実装してもOK)
これは必ず1secずつ増えてゆくはずです。ですから,毎秒その検査処理を入れます。
そして,1sec増えたという正常な状況ではなくなった時が発生したとしたら,その時に時刻の狂いが発生しています。

アプリ側で時刻のずれを検査する最高度の方法という事になるでしょう。
ご参考に。。

2013/11/20 10:49:52
id:wankodon

なるほど、そういうやり方もあるのですね。
遅れましたが有り難うございました。

2013/11/24 18:12:09

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません