MySQL で Grails 1.3.7 を使用しています。私のアプリケーション サーバーは、ユーザーが実行したクエリの検索結果を記録します。スキーマ (簡略化) は以下で構成されます。
class Query {
String query
String user
}
class Document {
String externalId
String title
}
class Posting {
Query query
Document document
int rank
}
ユーザーが初めてドキュメントを取得するクエリを実行するたびに、新しいインスタンスを作成します。それ以外の場合は、対応するインスタンスを作成するときに既存のインスタンスを再利用しPostingます。特定の に対して のインスタンスは 1 つだけ Document存在する必要がありますexternalIdが、複数のPostingインスタンスがそれを指すことができます。
複数のユーザーが同じドキュメントを取得するクエリを実行できますが、同時実行の問題が発生します。2 人のユーザーがほぼ同時に同じドキュメントを初めて取得した場合、 を作成しようとする 2 回目の試行はDocument、 での一意制約違反で失敗しexternalIdます。これはいい。悪いことPostingに、複製に関連付けられた新しく作成されたインスタンスDocumentもロールバックされます。保存を再試行する方法を理解するのが難しいため、これは良くありません。
私が思いついた解決策は、Documentを呼び出す同期メソッドを使用してを作成しsave(flush: true)、それが失敗した場合は、データベースからドキュメントを再度読み取ることです。次に、結果のドキュメント (保存または再読み込み) を使用して、Postingインスタンスに入力します。このソリューションは機能しますが、ユーザーが取得した結果を処理するには遅すぎます。パラメータを削除flush: trueするとパフォーマンスは向上しますが、インスタンスが適切に作成されるDocumentとPostingは限りません。
この種の更新を実装する正しい方法は何ですか?
明確化
私が実行しているクエリは、一度に 100 件の一致を返します。つまり、ユーザー リクエストごとに 0 Document~ 100 個のインスタンスと 100 個のインスタンスを作成しています。Posting