# MySQL の SYSDATE() と NOW() の違いを整理する
> MySQL の日付関数 SYSDATE() と NOW() の違いと使い分け、レプリケーションへの影響や設定オプションを整理します。
- Canonical: https://c-a-p-engineer.github.io/mysql-sysdate-vs-now/
- Published: 2025-10-05T00:00:00.000Z
- Modified: 2025-10-05T00:00:00.000Z
- Categories: Database
- Tags: Database, MySQL

MySQLで現在日時を取得する代表的な関数は `SYSDATE()` と `NOW()` の2つです。一見同じ値を返しそうですが、評価タイミングやレプリケーションとの相性が異なります。本稿ではそれぞれの挙動と使い分けの指針をまとめます。

## NOW() はステートメント開始時刻を返す
`NOW()`（およびエイリアスの `CURRENT_TIMESTAMP`）はステートメントの開始時刻をキャッシュし、同じステートメント内で複数回呼び出しても同じ値を返します。トランザクション中でも、各ステートメントの開始時刻が採用されるため、監査用の作成日時・更新日時に向いています。

```sql
SELECT NOW() AS first,
       SLEEP(2) AS wait,
       NOW() AS second; -- first と second は同じタイムスタンプ
```

トランザクション境界を跨いだ場合は、次のステートメントの開始時刻で再評価されるため、コミット時間と保存したタイムスタンプがずれにくいのが特徴です。

## SYSDATE() は呼び出し時のリアルタイム値を返す
`SYSDATE()` は呼び出し時点でサーバーが知る現在時刻を都度取得します。既定値のままでは、同一ステートメント内でも再評価されるため、処理の遅延を含めた実時計測に向いています。

```sql
SELECT SYSDATE() AS first,
       SLEEP(2) AS wait,
       SYSDATE() AS second; -- second は first より約 2 秒進む
```

コマンドラインオプション（またはシステム変数）で `sysdate_is_now = ON` を指定すると `SYSDATE()` も `NOW()` と同じくステートメント開始時刻を返すようになりますが、互換性確保のため既定では無効です。

## 主な違いの早見表
| 観点 | NOW() | SYSDATE() |
| ---- | ----- | --------- |
| 評価タイミング | ステートメント開始時に固定 | 呼び出しのたびに評価 |
| レプリケーション | ステートメントベースでも安全 | ステートメントベースでは非決定的で警告対象 |
| エイリアス・同義語 | `CURRENT_TIMESTAMP` など | なし（`sysdate_is_now` で挙動変更可） |
| 主な用途 | 作成日時・更新日時のトラッキング | 実際の処理時間測定、定期ジョブの時刻計測 |

## バイナリログとレプリケーションでの扱い
ステートメントベースのバイナリログ（`binlog_format = STATEMENT`）では、`SYSDATE()` の非決定的な挙動が複製先で異なる結果を招く恐れがあります。MySQL 8.0 では `SYSDATE()` を含むステートメントをログに書く際に警告が出力され、行ベースまたは混合モードへの切り替えが推奨されます。`NOW()` はステートメント開始時に固定されるため、既定設定でもレプリケーションが安全に行えます。

どうしても `SYSDATE()` を使いたい場合は、以下のいずれかを検討します。
- サーバー起動時に `--sysdate-is-now`（または `SET PERSIST sysdate_is_now = ON`）を設定し、挙動を `NOW()` と揃える
- バイナリログを行ベース（`ROW`）に切り替えて非決定的関数を含むステートメントを安全にレプリケーションする

## 使い分けの指針
- **監査用カラム（created_at / updated_at）やロック待ち時間の記録**には `NOW()`（または `CURRENT_TIMESTAMP`）を使うと、ステートメント単位で一貫した値を保存できます。
- **処理遅延の可視化やジョブ実行時刻の実測値**が必要な場合は `SYSDATE()` を利用すると、処理時間をタイムスタンプ差分で把握できます。
- **アプリケーションで実時間が重要だがレプリケーションも行っている**場合は、行ベースのバイナリログを選択するか、アプリケーション側で時刻を採取することで安全性を確保できます。

## まとめ
- `NOW()` はステートメント開始時刻を保持する決定的な関数で、監査カラム向きです。
- `SYSDATE()` は呼び出し時刻を常に更新するため、リアルタイム計測に適していますが、レプリケーション設定に注意が必要です。
- `sysdate_is_now` やバイナリログ形式を調整することで、要件に合わせた時刻取得が可能になります。

## 参考文献
- <a href="https://dev.mysql.com/doc/refman/8.0/ja/date-and-time-functions.html" target="_blank" rel="nofollow noopener">MySQL :: MySQL 8.0 リファレンスマニュアル :: 12.7 日付および時間関数</a>
