Salesforce開発でApexトリガーやApexクラスを書いていて、突然「Salesforce: Apex trigger too many DML rows」というエラーに遭遇して、頭を抱えていませんか? 大量データの一括処理を実装した途端に、このエラーでシステムが停止…なんて経験、私もあります。本当に困りますよね。
ご安心ください。これはSalesforce開発者なら誰しもが一度は通る道、ガバナ制限との戦いなんです。結論から言うと、このエラーの主な原因は、Salesforceの単一トランザクションにおけるDML操作の行数制限(10,000行)を超過した際に発生します。そして、解決策の肝は、処理を分割し、非同期処理に切り替えることです。特に、Batch Apexへの移行が最も効果的な手段となることが多いでしょう。
目次
1. エラーコード Salesforce: Apex trigger too many DML rows とは?(概要と緊急度)
このエラーメッセージが示す通り、Salesforceが定義しているガバナ制限の一つである「単一トランザクションで実行できるDML操作の行数」を超過した場合に発生します。具体的には、1つのトランザクション内でデータベースに対してINSERT, UPDATE, DELETEなどのDML操作を行った行数の合計が10,000行を超えた場合に発生します。
想像してみてください。あるトリガーが10,000件以上のレコードを更新しようとしたとき、その処理は途中で強制終了し、エラーメッセージが表示されます。これは、Salesforceのマルチテナント環境において、特定の組織がシステムリソースを独占しないようにするための重要な仕組みなのです。
2. 最速の解決策 3選
この「too many DML rows」エラーを解決するための、ベテランエンジニアが実践する鉄板の解決策を3つご紹介します。
解決策1: Batch Apexへの移行(最も推奨!)
大量データを扱う処理でこのエラーが発生した場合、真っ先に検討すべきはBatch Apexへの移行です。Batch Apexは、大量のデータを小さなチャンク(バッチ)に分割し、それぞれのチャンクを独立したトランザクションとして非同期で処理するためのフレームワークです。
- メリット: 各バッチ処理が新しいトランザクションとして扱われるため、DML行数制限を含むほとんどのガバナ制限が緩和されます。数百万件規模のデータ処理も可能になります。
- 使い方:
Database.Batchableインターフェースを実装し、start,execute,finishの3つのメソッドを記述します。
これを使えば、ほとんどの「too many DML rows」問題は解決します!
非同期処理の学習コストはかかりますが、長期的に見ればSalesforce開発における強力な武器となるでしょう。
解決策2: Queueable Apexの活用
Batch Apexほど大規模ではないけれど、やはり処理が重い、あるいは少しだけ非同期にしたい、という場合にはQueueable Apexも有効な選択肢です。
- メリット: 非同期で処理を実行し、DML行数制限から解放されます。Futureメソッドとは異なり、ジョブチェーン(次のQueueableジョブを呼び出す)が可能です。
- 使い方:
Queueableインターフェースを実装し、executeメソッド内で処理を記述します。
解決策3: Futureメソッドの検討
非常にシンプルに非同期処理をしたい場合、Futureメソッドも検討できます。ただし、DML行数制限対策としてはQueueableやBatchが優先されることが多いです。
- メリット: 最も手軽に非同期処理を実装できます。
- デメリット: 戻り値がなく、コールアウトでの利用がメインになることが多いです。また、一回のトランザクションで呼び出せる回数に制限があります。DML行数制限を直接的に緩和するというよりは、メインのトランザクションから切り離すことでエラーを回避するイメージです。
3. エラーの根本原因と再発防止策
一度エラーを修正しても、根本原因を理解していないと、また同じエラーでハマってしまいます。ここでは、なぜこのエラーが発生するのか、その根本原因と、二度とエラーを起こさないための再発防止策を解説します。
エラーの根本原因
- 非効率なDML操作(ループ内DML): 最も一般的な原因です。Apexトリガーやクラス内で、ループ処理の内側で
insert,update,deleteなどのDML文を実行していませんか? これだとループの繰り返し回数分DML操作が発生し、簡単に10,000行を超えてしまいます。 - 大量データの一括処理: データローダーなどを使って大量のレコードを一括で挿入・更新した際に、関連するトリガーやワークフローが連鎖的に起動し、結果的にDML操作の総行数が跳ね上がるケースです。
- 設計段階での考慮不足: システム設計時に、将来的に発生しうるデータ量を予測しきれていなかったり、ガバナ制限を十分に考慮していなかったりする場合も原因となります。
再発防止策
一度ガバナ制限の洗礼を受けたら、次からは意識が変わります。以下のポイントを常に念頭に置いてコーディングしましょう。
- DML操作はループの外で実行する: 複数レコードに対する更新が必要な場合は、まず更新対象のレコードをリストに集め、そのリストに対して一度にDML操作を実行するようにしましょう。
- SOQLも同様にループの外で: DMLだけでなくSOQLも同様です。ループ内でSOQLを発行すると、SOQLクエリ発行回数制限に引っかかります。
- Map型を有効活用する: 関連レコードの取得や更新では、Map型を使うことで効率的にデータを処理できます。
- 非同期処理の適切な利用: 大量データを扱う可能性がある処理は、最初からBatch ApexやQueueable Apexの利用を検討する癖をつけましょう。
- テストデータでの検証: 開発・テスト段階で、本番に近いデータ量をシミュレーションしてテストを行いましょう。少量のデータでは問題なくても、データ量が増えると途端にエラーになるのがガバナ制限の特徴です。
- ガバナ制限の知識を深める: Salesforce開発者である以上、ガバナ制限は常に意識すべき制約です。各種制限値を理解し、それらを考慮した設計・実装を心がけましょう。
4. まとめ
「Salesforce: Apex trigger too many DML rows」エラーは、Salesforce開発における「あるある」な問題の一つですが、その裏にはガバナ制限という重要なルールが潜んでいます。このエラーに遭遇した際は、まず単一トランザクションにおけるDML操作行数10,000行の制限を思い出してください。
そして、解決策の最有力候補はBatch Apexです。処理を非同期に切り替えることで、この強敵を乗り越えることができます。また、一度解決したら終わりではなく、バルク化の原則を忘れずに、常にガバナ制限を意識した堅牢なコードを書くことを心がけましょう。
今回の記事が、あなたのSalesforce開発におけるトラブルシューティングの一助となれば幸いです。私もかつてはこのエラーに何度も苦しめられましたから、あなたの気持ちはよく分かります。諦めずに、一緒に最高のシステムを作り上げていきましょう!
“`