ロックステートメント
Apex の FOR UPDATE では、レコードの更新中に sObject レコードをロックして、競合の条件やスレッドの安全性の問題の発生を回避できます。
sObject レコードがロックされると、他のすべてのクライアントとユーザーは、コードまたは Salesforce ユーザーインターフェースを使用して更新を行えません。レコードをロックしているクライアントは、レコードに対してロジックを実行し、更新を行うことができます。ロック中は、ロックされたレコードが別のクライアントによって変更されることはありません。トランザクションが完了するとロックが解除されます。
Apex の一連の sObject レコードをロックするには、インライン SOQL ステートメントの後に FOR UPDATE キーワードを埋め込みます。たとえば、次のステートメントでは 2 つの取引先を照会すると共に、返された取引先をロックします。
1Account [] accts = [SELECT Id FROM Account LIMIT 2 FOR UPDATE];ロックに関する考慮事項
- クライアントがレコードをロックしている間、そのクライアントは同一トランザクションでデータベースの項目値を変更できます。他のクライアントが同じレコードを更新するには、トランザクションが完了してレコードのロックが解除されるまで待機する必要があります。ロックされている間も、他のクライアントは同じレコードを照会できます。
- 別のクライアントが現在ロックしているレコードをロックしようとすると、プロセスは新しいロックを取得する前に、ロックが解除されるのを最大 10 秒間待機します。待機時間が 10 秒を超えると、QueryException が発生します。同様に、別のクライアントが現在ロックしているレコードを更新しようとし、ロックが最大 10 秒以内に解除されない場合は、DmlException が発生します。
- ロックされているレコードをクライアントが変更しようとした場合、update コールが行われてから短時間でロックが解除されれば、更新操作は成功する可能性があります。この場合、2 番目のクライアントがレコードの古いコピーを取得していると、ロックしていたクライアントが行った変更がこの更新によって上書きされる可能性があります。上書きを回避するには、2 番目のクライアントが最初にレコードをロックする必要があります。ロックプロセスは、SELECT ステートメントを使用してデータベースのレコードの最新のコピーを返します。2 番目のクライアントはこのコピーを使用して新しい更新を行うことができます。
- FOR UPDATE 句を介して Apex で取得されるレコードのロックは、コールアウトの実行時に自動的に解除されます。この情報はデバッグログに記録されます。記録されたメッセージには、最近ロックされたエンティティ種別が含まれます。例: FOR_UPDATE_LOCKS_RELEASE FOR UPDATE コールアウトにより解除されたロック。直近のロックは取引先でした。FOR UPDATE クエリが以前実行された可能性があるコンテキストでコールアウトを実行するときは注意してください。
- 1 つのレコードで DML 操作を実行すると、当該レコードのほか、関連レコードもロックされます。