質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.52%

  • データベース設計

    176questions

    データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

  • アーキテクチャ

    89questions

    アーキテクチャとは、情報システム(ハードウェア、OS、アプリケーション、ネットワーク等)の設計方法、設計思想、設計思想に基づいて構築されたシステム構造をアーキテクチャと呼びます

現在時刻をどのマシンで採るかの考え方

解決済

回答 6

投稿 編集

  • 評価
  • クリップ 5
  • VIEW 1,484

yuba

score 5206

直近で困っている事案ではないのですが毎度突き当たるたびにうーんとなることが多いので皆様のご意見・知見をいただきたく質問させていただきます。

例えばこの問答 DBから条件に当てはまったレコードを削除したい。|teratail なのですが、質問内容はもともとPHP製のアプリ側で現在時刻を取得していようとしており、ベストアンサーはSQL問い合わせ内で現在時刻を取得しています。

SQL問い合わせ内での「現在時刻」も意味が3種類くらいあったりして面倒なのですがそれは置いておくとして、ここで重要なのは現在時刻を提供するマシンがDBホストかアプリサーバホストかという違いが出ていることです。この違いには、いくつか意義の違いがあります。

DB側で現在時刻を取得する形にすると

  • ○ アプリサーバを多重化したときに、アプリサーバ間の時計のズレに関係なく一貫した時刻が取得でき、前後関係の矛盾が起こりません。
  • ○ アプリのプログラミングから時刻という要素を排除してシンプルなロジックにできます。ロジックに現在日時が必要な局面、たとえば「先週のなにか集計」を取得するときでも、DB問い合わせの結果の一部として「先週というのは○月○日からの7日間のことなんだけど」という数字も取れてくるような形にして局所的に押さえ込めます。
  • △ アプリ側の動作ログとDBのデータを付き合わせようとしたときに、タイムスタンプに時刻のズレがあって突き合わせが難しくなる可能性があります。対策はいろいろ考えられるものの。
  • × DBの問い合わせはアプリコードよりも単体テストが困難なので、時刻に絡んだ振る舞いのテストが不十分になりがち。アプリだったら、引数として時刻、もしくは時刻を吐くラムダ式を与える形にするなどでいくらでもテストしやすいコードにできます。
  • × 2番めにあげたメリットと表裏一体ですが、時刻を利用したきめの細かい処理はアプリ側で記述できなくなります。もしくは、自分の書き込んだデータを再度問い合わせてタイムスタンプを見るなどという冗長な処理をせざるを得なくなりえます。

一長一短ということはプロダクトの性質に合わせて選べば良いと言ってしまえばそれまでなのですが、リーンスタートアップでシステムの要件が今後どう育っていくかわからないという状況はよくあることで、決め手がない中で基礎のアーキテクチャを構築しましょうという段階からどう考えていくのがいいでしょうか。

自分自身はなんとなくでアプリ側採取を選択していることが多いのですが、実際上記1番目の矛盾の処理に悩むこともあり、さて… となっています。
各方式でのアンチパターン、対策方法など、知見があったら教えていただきたいです。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 6

checkベストアンサー

+9

DBに保存された日時のデータにシステム上意味があるのなら現在時間の取得は1か所で行わざるを得ないと思います。

  • 早い物順で何かを行う。(何かの申込みや登録を先着n件で締め切るとか)
  • 楽観的 排他制御の制御データとして使用する。
  • etc...その他あまり思いつかない 

質問内容はもともとPHP製のアプリ側で現在時刻を取得していようとしており、ベストアンサーはSQL問い合わせ内で現在時刻を取得しています。

「フロントアプリで取得する」についても
PHPのdate()で取得すればPHPが動作しているサーバー機器の現在時刻ですが、
select sysdate from dual;(oracleの場合)でDBサーバーから取得し、これをdeleteの条件として渡せば一貫して「日時の情報はDBサーバーのものを使用する」ことになると思います。

このように、要件に合わせてどのようなデータにどこの日時を基準とするかをシステムとして統一して決めておけば問題になる事はそうそうないと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/13 13:18

    DBをアプリにとってのタイムサーバーとしても扱うというの、それは単純ですがいい考えですね。
    そうすると時刻源はDBプライマリホスト、と決めるのにあまり問題なくなります。

    キャンセル

+3

こんにちは。

私なら時刻を一貫させることを結構重視すると思います。特に受注時刻など、金銭が絡む時刻は1ヶ所で管理したいです。複数のサーバで受注時刻を定義するとビジネス上のトラブルが起きた時、めんどうなことになりそうな気がします。(実際に経験したことはないので推測です。)
ですので、リンク先のケースでは、受注時刻がDBサーバの時刻で定義されていることになるので、受注キャンセル処理のための現在時刻もDBサーバで取得したいところです。
アプリサーバの時刻とDBサーバの時刻の誤差が事実上管理されているようであれば、誤差分のマージンを取ってアプリサーバで現在時刻を取得することも有りと思いますが、運用まで検証しないといけないのでその手間が痛い気がします。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/13 15:23

    誤差分のマージンを取って、っというのが△のところで書いた「対策は考えられるものの」の具体的な対策の一つでした。絶対そんな手間かけたくないとは思いつつ。はい。

    キャンセル

+2

必ず他のクエリが伴う限りは、DBから時刻を持ってくる仕様の方がアプリサーバーの連携間の問題等も考えなくてよく、場合によってはDB上での最適化も効きやすいのではないかと思います。

ただ、プロジェクト初期段階では、バックエンドに何を指定するかということも変わる可能性はあると思います。
現在時刻取得関数はRDBMS間で仕様が異なる場合が多く、後で変更となった時に面倒になる場面もあるかもしれません。(RDBじゃなくなる可能性もあるかも)

よって、個人的には初期段階ではアプリで時刻を入れ、問題になった場合のみDBから取得に切り替える方がいいのではないかと思いました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/13 15:19

    時刻取得をそういう関数かなにかにして抽象化しておき、切り替え自体を容易にするというアプローチですね。

    キャンセル

  • 2017/02/13 15:58

    そうですね、後はDBでも時間の巻き戻りとか発生したら時間はずれると思うので、あまり厳密に合わせることもないかなというのも、"最初はアプリで"という根拠の一つです。

    キャンセル

+1

時間の粒度が秒単位でいいのなら、「全部のサーバをNTPで合わせておく(どのマシンの時計も秒単位では一致する)」というのも、現実的な解決策ではないかと思います。

カード処理のセキュリティ基準であるPCI DSSでも、サーバの時計を合わせておくことを求めています(参考)。逆に、システム内で時計がずれていては、ログを突き合わせても正しく時系列が把握できず、別なトラブルとなりかねません。

秒未満まで考えるとなると、HTTPでの通信やレスポンス処理だけでも100ミリ秒くらいはすぐに経過してしまうので、そこまで必要なら「度のタイミングで時間を取得するのか」まで、本腰を入れて考えないといけなくなります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/13 15:21

    うーん、粒度低めでいくのは、ログとDBデータの突き合わせについては問題なくなりますが、前後関係の矛盾は抑えきれないかと思います。

    「現在時刻とは何か」というのを本腰を入れて定義すべきなのはまったくおっしゃる通りかと思います。マイクロサービス化でより曖昧になりつつありますが。

    キャンセル

  • 2017/02/13 15:56

    MySQL 5.6.5以降はDATETIMEやTIMESTAMPがマイクロ秒まで対応したこと、そして標準SQLではマイクロ秒までの格納がデフォルトだということを知りました(https://dev.mysql.com/doc/refman/5.6/ja/fractional-seconds.html)。

    上のコメントは、それ以前のMySQLのように、主として「そもそも秒単位のデータしかない」シチュエーションを念頭に置いていました。

    キャンセル

+1

本質問とは外れますが、「順序」についての考察が出てきたので
それについての回答(意見)です。

厳密な順序の基準としては、日時は使わず番号(連番)を使うのがより正確で一般的だと思います。

たとえば以下のような処理はよくあると思います。

  • 処理要求に対して、まず受付番号(連番)を振ります。受付日時の扱い(締め切り)がデリケートな処理ではここで日時チェックを行い不備があれば突き返します。
  • 受付番号の順に処理します。
  • 処理が完了したら完了番号を振り出して、処理済伝票(レコード)に完了番号を振って保存します。

この伝票(レコード)に記録すべき日時を受付時点、完了時点にするか(あるいは両方)は
その処理(伝票)の意味や前後の処理の関係性によりケースバイケースだと思います。

順序が重要な照会処理では、伝票番号順に並べて結果を返します。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/13 16:10

    連番値が受付順序になっているという前提、私も個人的には好きなのですが、世間的にはそれを前提にしないのが潮流になっているかなと感じます。
    アプリフレームワークがDBからまとめて20個くらい連番値を採番してプールする、みたいな動作が結構よくあるんですよね(Java系フレームワークでよく見ます)。これによりアプリサーバを多重化した時点で受付順と連番値は対応しなくなります。Play Frameworkみたいな多重化ありきのフレームワークでもそうなので、これが世間の流れってことかなと。

    キャンセル

  • 2017/02/13 16:35

    そうなのですね。古い人間なので、シビアなタイミングに日時を使うのはできれば避けたいと考えています。しかし分散処理など考えると一意な連番振るのも難しいケースもありえるのですね。

    キャンセル

-2

Oracleですが、海外に支店や店舗を持っている会社でSYSDATECURRENT_DATEを取得しているシステムを扱ったことがあります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/13 12:41

    はい、そういうことは(開発担当者の不注意のせいも含めて)たまにみかけますが、そのこととこの問題とどのような関わりがあるのでしょうか…?

    キャンセル

  • 2017/02/13 13:07

    たとえば、単位時間毎の集計や日計などで時差を考慮する必要があります。
    休日は国によって違うとか次の営業日を取得する時に考慮することが必要な場合もあります。

    キャンセル

  • 2017/02/13 13:20

    何か別の質問への回答を間違ってこちらにつけられたのでしょうか…?

    キャンセル

  • 2017/02/21 20:32

    タイムゾーンへの考慮が必要な話題かと思ったのですが、外したでしょうか?

    キャンセル

  • 2017/02/21 20:39

    マシン間の時間のずれというのは、NTPでもあわせきれないミリ秒単位のずれのことを指していました。

    キャンセル

  • 2017/02/22 08:55

    そうでしたか。
    DB LINKを多用するシステムでもパフォーマンス・チューニングで苦労させられることはありますが、時間の動機でそこまでの精度を要求されたこともないです。
    マシン間の時間を完全に同期させるツールってありそうな気がしますが、さがしたことはありません。

    キャンセル

同じタグがついた質問を見る

  • データベース設計

    176questions

    データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

  • アーキテクチャ

    89questions

    アーキテクチャとは、情報システム(ハードウェア、OS、アプリケーション、ネットワーク等)の設計方法、設計思想、設計思想に基づいて構築されたシステム構造をアーキテクチャと呼びます