私は、アカウントとこれらのアカウントを介して行われたトランザクションを処理するアプリケーションを開発してきました。
現在、アプリケーションが使用するテーブルは次のようにモデル化されています。
アカウント + ---- + ----------------- + --------- + ----- + | id | current_balance | バージョン| ... | + ---- + ----------------- + --------- + ----- + | 1 | 1000 | 48902 | ... | | 2 | 2000 | 34933 | ... | | 3 | 100 | 103 | ... | + ---- + ----------------- + --------- + ----- + account_transaction + ------ + ------------- + ---------------------- + ----- ---- + ------------------ + ----- + | id | account_id | 日付| 値| 結果の量| ... | + ------ + ------------- + ---------------------- + ----- ---- + ------------------ + ----- + | 101 | 1 | 2012年5月3日10:13:33| 1000 | 2000 | ... | | 102 | 2 | 2012年5月3日10:13:33| 500 | 1500 | ... | | 103 | 1 | 2012年5月3日10:13:34| -500 | 1500 | ... | | 104 | 2 | 2012年5月3日10:13:35| -50 | 1450 | ... | | 105 | 2 | 2012年5月3日10:13:35| 550 | 2000 | ... | | 106 | 1 | 2012年5月3日10:13:35| -500 | 1000 | ... | + ------ + ------------- + ---------------------- + ----- ---- + ------------------ + ----- +
アプリケーションが新しいトランザクションを処理するたびに、account_transactionに新しい行を挿入し、アカウントテーブルで、アカウントの現在の残高と楽観的ロックに使用される列バージョンを格納する列current_balanceを更新します。楽観的ロックが機能する場合、トランザクションはコミットされます。機能しない場合、トランザクションはロールバックされます。
大まかな例として、トランザクション102を処理するとき、アプリケーションは次の疑似SQL/JAVAを実行しました。
autocommit=0に設定します。 account_transactionに挿入します (account_id、date、value、resulting_amount) 値 (2、sysdate()、550、2000); アカウントセットを更新する current_balance = 2000、 バージョン=34933 どこ id=2および バージョン=34932; if(ROW_COUNT()!= 1){ ロールバック; } そうしないと { 専念; }
ただし、特定のアカウントは非常にアクティブであり、多くの同時トランザクションを受信するため、アカウントテーブルの行を更新しているときにMySQLでデッドロックが発生します。これらのデッドロックは、データベースでデッドロックが発生したときにトランザクションが再処理されるため、アプリケーションに重大なパフォーマンスの低下をもたらします。
アカウントの現在の残高を効率的に処理するにはどうすればよいですか?現在の残高は、新しいトランザクションを承認/拒否するために必要であり、さまざまなレポートで使用されます。