0

組織で作業指示書を追跡するために開発している MySQL データベース (InnoDB) があります。複数の「サイト」があり、各サイトには 100 から始まる作業指示番号があります。

WorkorderID    SiteID    SiteWorkorderNum
     1           1            100
     2           1            101
     3           2            100

WorkorderIDは自動インクリメント フィールドです。
SiteIDSiteWorkorderNumは、両方とも一意の制約として設定されます。

特定のサイトに新しい作業指示書が挿入されるときはいつでも、アプリケーションはログインしているユーザーのサイト ID の max(SiteWorkorderNum) をチェックし、その値を挿入ステートメントに返します。私が避けたい問題は、同じサイトの 2 人のユーザーがまったく同時に新しい作業指示書を入力した場合です。

考えられる解決策がいくつかありますが、それぞれに欠点があるため、より良い方法があるかどうかを確認したいと思いますが、1つは他の方法よりも優れていると確信しており、もちろん新しいアイデアを受け入れています.

1)テーブルをロックして、値を取得して挿入するまで、他のユーザーが SiteWorkorderNum 値を取得しないことを保証します (ただし、何千ものユーザーが毎分作業指示を入力しようとしているとしましょう。 )

2)テーブルをロックせず、次に使用可能な SiteWorkorderNum を取得してデータベースに挿入しようとします。一意の制約エラーが発生した場合は、エラーをキャッチして、成功するまで再試行します。(これにより、テーブルが解放されたままになる可能性がありますが、同じサイトに何千人ものユーザーがいると仮定すると、複数のデータベース呼び出しは少し効率が悪いでしょうか?)

これらのソリューションのいずれかがパフォーマンスにどのように影響するかについて、私は偏執的すぎますか? もちろん、何千人ものユーザーはいませんが、トラフィックの多いプロジェクトに取り組む場合に備えて、この設計にベスト プラクティスを適用したいと考えています。

4

1 に答える 1

0

1 つのオプションは、トランザクションを使用することです。SELECT MAX(SiteWorkorderNum) ... WHERE SiteID=...結果の挿入と一緒に実行すると、すべてが機能するはずです。唯一の問題は、トランザクションが失敗する可能性があり、ユーザー エクスペリエンスが低下する可能性があることです。

私が以前に使用したもう 1 つのスキームは、列SiteIdNextWorkorderNum列を持つ割り当てテーブルを使用することです。するだけですUPDATE SiteWorkorderAlloc SET @Num=NextWorkorderNum, NextWorkorderNum=NextWorkorderNum+1 WHERE SiteId=...。次に @Num を取得して、後続の挿入でワークオーダー番号として使用します。これは問題なく動作しますが、唯一の小さな欠点は、ワークオーダー番号の取得と挿入の間にクラッシュが発生した場合、そのワークオーダー番号が失われる (使用されない) ことです。

于 2012-06-09T06:14:14.207 に答える