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

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

新規登録して質問してみよう
ただいま回答率
85.48%
アーキテクチャ

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

データベース設計

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

Q&A

解決済

6回答

8764閲覧

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

yuba

総合スコア5568

アーキテクチャ

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

データベース設計

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

4グッド

5クリップ

投稿2017/02/13 03:13

編集2017/02/13 03:16

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

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

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

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

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

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

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

KiyoshiMotoki, musix55, satouryou👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答6

0

ベストアンサー

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

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

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

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

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

投稿2017/02/13 04:01

Y.H.

総合スコア7914

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuba

2017/02/13 04:18

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

0

こんにちは。

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

投稿2017/02/13 04:12

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuba

2017/02/13 06:23

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

0

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

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

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

投稿2017/02/13 06:01

skitoy4321

総合スコア229

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuba

2017/02/13 06:19

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

2017/02/13 06:58

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

0

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

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

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

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

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

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

投稿2017/02/13 06:55

can110

総合スコア38266

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuba

2017/02/13 07:10

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

2017/02/13 07:35

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

0

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

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

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

投稿2017/02/13 05:54

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuba

2017/02/13 06:21

うーん、粒度低めでいくのは、ログとDBデータの突き合わせについては問題なくなりますが、前後関係の矛盾は抑えきれないかと思います。 「現在時刻とは何か」というのを本腰を入れて定義すべきなのはまったくおっしゃる通りかと思います。マイクロサービス化でより曖昧になりつつありますが。
maisumakun

2017/02/13 06:56

MySQL 5.6.5以降はDATETIMEやTIMESTAMPがマイクロ秒まで対応したこと、そして標準SQLではマイクロ秒までの格納がデフォルトだということを知りました(https://dev.mysql.com/doc/refman/5.6/ja/fractional-seconds.html)。 上のコメントは、それ以前のMySQLのように、主として「そもそも秒単位のデータしかない」シチュエーションを念頭に置いていました。
guest

0

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

投稿2017/02/13 03:38

Orlofsky

総合スコア16415

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuba

2017/02/13 03:41

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

2017/02/13 04:07

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

2017/02/13 04:20

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

2017/02/21 11:32

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

2017/02/21 11:39

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

2017/02/21 23:55

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問