15

InnoDBエンジンを搭載したMySQLにテーブルv_extがあります:-id
:主キー
-コード:事前に生成されたコードのリスト(たとえば、1000個のコードがランダムに生成されます)
-user_id:最初はNULL

ユーザーがアイテムを購入すると、コードを受け取ります。user_id列に入力するようにテーブルを更新する必要があります。私には2つの選択肢があります:

START TRANSACTION;
SELECT id FROM v_ext WHERE user_id IS NULL LIMIT 1 FOR UPDATE; -- return id 54 for ex.
UPDATE v_ext SET user_id=xxx WHERE id=54;
COMMIT;

また

UPDATE v_ext SET user_id=xxx WHERE user_id IS NULL LIMIT 1;

何千人ものユーザーが同時に購入している場合、2番目のオプションは安全ですか?もしそうなら、この2番目のオプションは1つのクエリしか必要としないため、パフォーマンスに優れていると想定するのは正しいですか?

4

1 に答える 1

18

答えが得られなかったので、ベンチマークを開始しました。私の基準は次のとおりです。

  • 20,000 の事前生成コード
  • ab20,000 リクエスト、100 同時実行での Apache コマンドの使用:ab -n 20000 -c 100
  • サーブレット -> EJB (JPA 2.0 EclipseLink、JTA) を使用して DB で更新を実行します (実際の状況では JSF アクションを介して行われるため)
  • サーブレットの 2 つのバージョン、1 つはオプション 1 (SELECT ... FOR UPDATE )、もう 1 つはオプション 2 (UPDATE ... LIMIT 1)
  • Glassfish を停止し、テスト済みのサーブレットを手動で 5 回ヒットしてウォームアップし、user_id をすべて NULL にリセットします
  • テストはそれぞれ 3 回実行され、平均が提供されます

結果:

SELECT ... FOR UPDATE; アップデート ... :

Concurrency Level:      100
Time taken for tests:   758.116 seconds
Complete requests:      20000
Failed requests:        0
Write errors:           0
Row updated:            20000

更新....制限1:

Concurrency Level:      100
Time taken for tests:   773.659 seconds
Complete requests:      20000
Failed requests:        0
Write errors:           0
Row updated:            20000

したがって、少なくとも私のシステムでは、2 つのクエリを使用するオプションは、1 つのクエリよりも効率的です。私はそれを期待していませんでした:)

于 2012-12-27T06:00:31.763 に答える