3.4. デッドロック

ロックを使っているので、デッドロックが起こる可能性はあります。ただし、Neo4j は、デッドロックの発生前に (ロックを取得することによって生じる) デッドロックを検出し、例外をスローします。そして、例外がスローされる前に、トランザクションはロールバックとマークされます。 該当するトランザクションによって取得されたすべてのロックは依然保持されますが、トランザクションが終了すると、これらのロックは (すでに説明したように finally ブロックの中で) 解放されます。ロックが解放されると、デッドロックの原因となっていたトランザクションの保持するロックが解放されるのを待っていたほかのトランザクションは、処理を先に進めることができます。デッドロックの原因となっていたトランザクションによって実行された作業の内容は、必要に応じてユーザーが回収することができます。

デッドロックが頻繁に起こる場合は、並行する書き込みリクエストが行われていて、独立性と一貫性を保ちながらこれらの書き込みリクエストを実行することができないことを示しています。このようなケースでは、並行更新が合理的な方法で行われるようにすることが解決策になります。たとえば、2 つの特定ノード (A および B) があって、各トランザクションでこれらのノードの両方に対して順番を定めずにリレーションの追加または削除を行う場合、2 つ以上のトランザクションが並行してこのような操作を行うと、デッドロックが発生します。この場合、1 つの解決策は、更新を常に同じ順序 (最初に A、次に B) で行うようにすることです。別の解決策として、各スレッド/トランザクションがノードやリレーションに対してほかの並行トランザクションと矛盾するような書き込みを行わないようにする方法があります。この解決策は、具体的には特定タイプのすべての更新を 1 つのスレッドだけに担当させることで実現できます。

[重要項目]重要項目

Neo4j が管理しているロック以外の同期メカニズムの使用に起因するデッドロックも発生する可能性があります。Neo4j API のすべての操作は、特に断りのない限りスレッドセーフなので、外部の同期メカニズムは不要です。同期メカニズムを必要とするほかのコードは、同期化ブロック内では一切 Neo4j の操作を行わないようにする形で、同期化を行う必要があります。