サイトアイコン IT NEWS

CRONとSQLを使った定期処理で重複を防ぐためのテクニック

Webシステムでは、CRONを使って定期的に処理を実行することが常に行われます。
しかし、CRONによるデータ処理では、重複したデータを再度処理してしまう問題が発生する場合があります。
この問題を解決するためには、データが重複しないようにWHERE区を改善する必要があります。

問題の解析

データを取得するために、下記のようなWHERE区を使用しているとします。

WHERE update_dt >= NOW() - INTERVAL '5 minutes'

この条件は、現在時刻から5分前以降のデータを取得するため、CRONが5分間隔で実行されると、同じデータが繰り返し取得されます。

これは、例えば誰かにメッセージを送るという処理において、同じ人に同じメッセージが複数回送られてしまう問題を導きます。

解決策

WHERE区に下記の条件を追加することで、同じデータが重複して取得されるのを避けることができます。

改善されたWHERE区

WHERE update_dt + INTERVAL '5 minutes' >= NOW()

このWHERE条件は、データのkaishi_dtに5分を足した時刻が、現在時刻以降である場合のみデータを取得します。
これにより、同じデータが重複して処理される問題を解決できます。

プログラムコードの例

改善されたWHERE区を使用した実際のプログラムの例を下記します。

const queryText = `
  SELECT info_name, info_message
  FROM information
  WHERE update_dt + INTERVAL '5 minutes' >= NOW() AND del_flg = FALSE
`;

const sendInformation = async (client) => {
  try {
    const query = { text: queryText };
    const result = await client.query(query);

    for (const row of result.rows) {
      await sendMessage(row.info_name, row.info_message);
    }
  } catch (err) {
    logger.Error(err.stack, 'sendInformation');
  }
};

その他の時間や日数の例

さまざまな時間や日数に対応した条件をWHERE区に記述する方法もご紹介します。

過去1時間以内のデータを取得

WHERE update_dt + INTERVAL '1 hour' >= NOW()

過去1日以内のデータを取得

WHERE update_dt + INTERVAL '1 day' >= NOW()

過去7日以内のデータを取得

WHERE update_dt + INTERVAL '7 days' >= NOW()

過去30分以内のデータを取得

WHERE update_dt + INTERVAL '30 minutes' >= NOW()

このアプローチの利点

可読性の高いWHERE区

update_dt + INTERVALを使用することで、問題の解決に直接繋がります。

既存データの変更不要

新たなフラグやカラムを追加する必要がないため、データモデルを変更せずに実装できます。

柔軟性のある適用

条件を変更するだけで、必要な時間や日数に合わせたデータを簡単に取得できます。

パフォーマンスの保持

WHERE区だけの改善なので、処理を平均化し、システム全体のパフォーマンスを損なうことがありません。

まとめ

CRONによる定期処理でデータが重複する問題は、シンプルなWHERE区の改善で効果的に解決できます。
この方法を活用すれば、システムの安定性と効率性を向上させることが可能です。
さらに、時間や日数に応じた柔軟な対応も容易に行えるため、さまざまなケースに適用できます。

ぜひ、今回ご紹介したテクニックをあなたのシステムに活用してみてください!

モバイルバージョンを終了