

# Aurora PostgreSQL Limitless Database の分散デッドロック
<a name="limitless-query.deadlocks"></a>

DB シャードグループでは、異なるルーターとシャードに分散されているトランザクション間でデッドロックが発生する可能性があります。例えば、次の図に示すように、2 つのシャードにまたがる 2 つの同時分散トランザクションが実行されているとします。

![\[2 つの分散トランザクションでの分散デッドロック。\]](http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/images/limitless_distributed_transaction_deadlock.png)


トランザクションは、次のようにテーブルをロックし、2 つのシャードに待機イベントを作成します。

1. 分散トランザクション 1:

   ```
   UPDATE table SET value = 1 WHERE key = 'shard1_key';
   ```

   これは、シャード 1 のロックを保持します。

1. 分散トランザクション 2:

   ```
   UPDATE table SET value = 2 WHERE key = 'shard2_key';
   ```

   これは、シャード 2 のロックを保持します。

1. 分散トランザクション 1:

   ```
   UPDATE table SET value = 3 WHERE key = 'shard2_key';
   ```

   分散トランザクション 1 はシャード 2 を待機しています。

1. 分散トランザクション 2:

   ```
   UPDATE table SET value = 4 WHERE key = 'shard1_key';
   ```

   分散トランザクション 2 はシャード 1 を待機しています。

このシナリオでは、シャード 1 もシャード 2 も問題を認識していません。トランザクション 1 はシャード 2 でトランザクション 2 を待機し、トランザクション 2 はシャード 1 でトランザクション 1 を待機しています。全体的な視点では、トランザクション 1 はトランザクション 2 を待機しており、トランザクション 2 はトランザクション 1 を待機しています。2 つの異なるシャードの 2 つのトランザクションが互いに待機しているこの状況は、分散デッドロックと呼ばれます。

Aurora PostgreSQL Limitless Database は、分散デッドロックを自動的に検出して解決できます。DB シャードグループのルーターは、トランザクションがリソースの取得を待つ時間が長すぎると通知を受け取ります。通知を受け取るルーターは、DB シャードグループ内のすべてのルーターとシャードから必要な情報を収集し始めます。次に、ルーターは、DB シャードグループの残りのトランザクションが相互にブロックされることなく続行できるようになるまで、分散デッドロックに参加しているトランザクションを終了します。

トランザクションが分散デッドロックの一部であり、ルーターによって終了されると、次のエラーが表示されます。

```
ERROR: aborting transaction participating in a distributed deadlock
```

`rds_aurora.limitless_distributed_deadlock_timeout` DB クラスターパラメータは、分散デッドロックをチェックするようにルーターに通知する前に、各トランザクションがリソースを待機する時間を設定します。ワークロードでデッドロック状態が発生しにくい場合は、パラメータ値を増やすことができます。デフォルト値は `1000` ミリ秒 (1 秒) です。

クロスノードデッドロックが検出され解決されると、分散デッドロックサイクルが PostgreSQL ログに発行されます。デッドロックの一部である各プロセスに関する情報には、以下が含まれます。
+ トランザクションを開始したコーディネーターノード
+ コーディネーターノード上のトランザクションの仮想トランザクション ID (xid) (`backend_id/backend_local_xid` 形式)
+ トランザクションの分散セッション ID