2009-07-09 1 views
9

一般的なサスアプリケーションで特定のユーザのauto_incrementing整数を生成するにはどうすればよいですか?マルチユーザサースアプリケーションで連番を生成

たとえば、特定のユーザのすべての請求書の請求書番号はauto_incrementingで、1から始める必要があります。この場合、rails idフィールドはすべてのユーザで共有されるため、使用できません。

私の頭の上から外して、ユーザーが持っているすべての請求書を数えてから1を追加することはできますが、もっと良い解決策を知っている人はいますか?

答えて

4

任意の関係データベースのための典型的な解決策は、

user_invoice_numbers (user_id int primary key clustered, last_id int) 

ようなテーブルとストアド・プロシージャまたは

update user_invoice_numbers set last_id = last_id + 1 where user_id = @user_id 
select last_id from user_invoice_numbers where user_id = @user_id 

ようなSQLクエリ各ユーザがいくつかを持っている場合は、(ユーザーのために働くかもしれません同じ会社内の異なるユーザーからのトランザクションが互いにブロックする可能性があり、この表にパフォーマンスのボトルネックが存在するため、企業では機能しません(たとえば、企業のインボイス番号が必要な場合など)。

確認する必要がある最も重要な機能要件は、であるかどうかにかかわらず、システムに隙間があるかどうかを確認することです。標準のauto_incrementを使用するとギャップが許されます。ほとんどのデータベースでは、トランザクションをロールバックすると、増分された数値はロールバックされないためです。これを念頭に置いて、次のガイドラインのいずれかを使用してパフォーマンスを向上させることができます

1)長期実行トランザクションから新しい番号を取得するために使用する手順を除外します。インボイスに挿入するプロシージャは、複雑なサーバー側ロジックを持つ長期実行トランザクションであるとします。この場合、最初に新しいIDを取得し、別のトランザクションで新しい請求書を挿入します。最後のトランザクションがロールバックされると、自動番号は減少しません。しかし、user_invoice_numbersは長い間ロックされないので、多くの同時ユーザーが請求書を同時に挿入する可能性があります。

2)従来のトランザクションデータベースを使用して各ユーザーのlast idを持つデータを保存しないでください。キーと値の単純なリストを維持する必要がある場合は、その作業を行うことができる、小さくても速いデータベースエンジンがたくさんあります。 List of Key/Value databases。恐らくmemcachedが最も人気があります。以前は、Windowsレジストリやファイルシステムを使用して単純なキー/値の格納が実装されているプロジェクトを見ていました。各ファイル名がキーであり、各ファイルの中に最後のIDがあるディレクトリがありました。そして、この大まかな解決策は、ロックが非常に迅速に発行され、リリースされ、トランザクションのスコープに関与しなかったため、SQLテーブルを使用する方が優れていました。

私の提案が最適化のために複雑すぎるように見える場合は、実際にパフォーマンスの問題にぶつかるまで、これを忘れてください。ほとんどのプロジェクトでは、追加のテーブルを持つ簡単なメソッドはかなり高速に動作します。

+0

私は編集/削除請求書を許可していないので、全体を少し簡略化します(ギャップはありません)。しかし、私は今パフォーマンスについて心配していません。 ありがとうございます –

+0

memcachedはデータベースエンジンではありません:http://code.google.com/p/memcached/wiki/FAQ#How_can_I_use_memcached_as_a_database? –

+0

ギャップを生じる可能性のあるテクノロジ(この回答の自動インクリメントから表示されるような)を使用すると、シーケンスからチャンクを事前取得できるようにすることで競合を減らすことができます。最悪の場合、未使用のチャンクを失います。 – djna

0

これが最善の解決策であるかどうかは不明ですが、最後の請求書IDをユーザーに保存してから、そのユーザーの新しい請求書を作成する際に次のIDを決定することができます。しかし、この単純な解決策は完全性に問題があり、注意する必要があります。

+0

請求書ID属性は、実際にユーザーオブジェクトに属していますか?実用的な解決策ですが、純粋主義者のためのものではありません! –

+0

インボイス番号が各ユーザーごとに区切られている必要がある場合は、「latestInvoiceNumberForThisUser」がユーザーと密接に関連しているようです。 – djna

+0

はい、よく議論されています。 –

2

ユーザーの最新の請求書番号を追跡する、「ユーザー」テーブルに関連付けられた別のテーブルを導入することができます。ただし、この値を読み取るとデータベースクエリが発生するため、提案したとおり、ユーザーの請求書を取得して追加することもできます。いずれにせよ、それはデータベースヒットです。

2

各ユーザー/顧客ごとにインボイス番号が独立している場合、ユーザーに関連付けられている一部の永続ストア(たとえばDBレコード)の「lastInvoice」フィールドがかなり避けられないようです。しかし、これは "最新の"番号のためのいくつかの競合につながる可能性があります。

1、2、3、5の請求書を送信し、請求書を送信しない場合、実際に問題がありますか 4?あなたが要件を少し緩和することができれば。

要件が実際には「すべての請求書番号は一意でなければならない」場合、私たちはすべての通常のID生成トリックを見ることができ、これらは非常に効率的です。

数字がシーケンシャルであることを確認することで、複雑さが増し、ビジネス上の利点が増えますか?

+0

はい、会計アプリケーションなので、数値は自動インクリメント整数である必要があります。だから、それはあまりにも堅実である必要があります。 –

0

実際に請求書IDを増分形式で生成しますか?セキュリティホールを開けないでしょうか(ユーザーが請求書番号の生成を推測できれば、要求に応じて情報を変更して情報開示につながる可能性があります)。 私は理想的に数字をランダムに生成します(そして、使用された数字を追​​跡します)。これにより、衝突も防止されます(数値が範囲内でランダムに割り当てられるため、衝突の可能性が減ります)。

+1

一部の国では、法的な乱数ではありません。州政府の検査のためのものでなければならない。 – Juanin

1

私は(数年後半決してよりも優れています!)あなたの必要性を解決する必要があります宝石をアップロードしました:)

https://github.com/alisyed/sequenceid/

関連する問題