0

少し紹介: URL や他の場所で使用するために公開される一意の ID の種類について熟考した後、線形合同ジェネレーター ( http://en.wikipedia.org/wiki/Linear_congruential_generator ) を選択しました。UUID や自動インクリメントがないのはなぜですか?

  • UUID は長すぎて、db に格納するのが困難です (推奨される方法は、それらを VARBINARY(16) に変換することです)。
  • Auto_increment は、一連の登録と新しいエンティティの追加を公開し、次の ID を予測する機能を提供します。たとえば、サービスが人気を博した場合、ユーザーは複数の登録を行ってナイス ID を取得し、そのようなアカウントを販売しようとすると、ID はある種のステータスを与えます。登録が早いほどクールです。私はそのようなことを避けることを好みます。

LCG を使用すると、シーケンスがランダム化され、可能な値が特定の目的のデータ型にうまく収まるようにパラメーターを選択できます。たとえば、ユーザー ID に INT UNSIGNED を使用し、パラメータを選択して 2^32 の期間を指定します。

問題は、次の ID を生成するには、最後の ID の値を取得する必要があることです。

nextId = (a * lastId + c) % m
  1. 私が理解しているように、最初のIDを自分で設定する必要がありますか? どの番号を選択するかは重要ですか?
  2. 新しいIDを生成するきちんとした方法は何ですか? おそらく、各テーブルの最後に生成された ID のリストを含むテーブルを作成しますか? または、各テーブルに auto_increment 列を追加して、最後に生成された ID を追跡しますか? また、短時間に大量の登録がある場合の問題を回避するにはどうすればよいですか?

Update1: ここからの情報を使用して、マルチユーザーに安全な1つのアプローチを見つけました: http://dev.mysql.com/doc/refman/5.5/en/information-functions.html#function_last-insert-id

CREATE TABLE sequences (users INT UNSIGNED NOT NULL, posts BIGINT UNSIGNED NOT NULL);
INSERT INTO sequences VALUES(123456,123456789);

次に、新しい ID を取得します。

UPDATE sequences SET users=LAST_INSERT_ID((a * users + c) % m);
SELECT LAST_INSERT_ID();
4

1 に答える 1

1

MySQL でこれを確実に行うには、ストアド プロシージャを記述し、最新の ID を持つ 1 行のテーブルを使用する必要があります。

ストアド プロシージャは、テーブルをロックし、最新の ID を読み取り、新しい ID を生成し、それをテーブルに更新し、テーブルのロックを解除して、新しい ID を呼び出し元に返す必要があります。

生成した ID のリストを含む複数行のテーブルを保持することもできます。その場合、ストアド プロシージャはロックし、最後に生成された ID を読み取り、新しい ID を生成し、それをテーブルに挿入し、ロックを解除して、返す必要があります。明らかに、この場合、最後に生成された ID を見つけるための信頼できる方法が必要になります。おそらく、自動インクリメント列と ID 列を使用するとうまくいくでしょう。

目的を達成する別の方法は、複数桁の乱数 (少なくとも 48 桁の 2 進数を使用します) を生成するストアド プロシージャを記述し、それをテーブルの主キーとして挿入することです。キーの衝突により挿入が失敗する限り、別の乱数を試してください。これらの長い乱数は、LCG シーケンスよりもさらに予測が困難です。

ストアド プロシージャを開発したら、実稼働環境に置く前に、マルチクライアントの負荷が高い状態でストアド プロシージャを厳密にテストする必要があります。十分にテストしないと、申し訳ありません。私は経験上、これを正しく行うのが難しいことを知っています。

UUIDには、あなたが言及したサイズの欠点があります。しかし、これには非常に強力な利点があります。徹底的にテストされています。選択した場合、車輪の再発明を試みる必要はありません。(ホイールを再発明した経験から、いくつかのパンクしたタイヤを思いつきました。)

于 2013-06-03T22:34:11.870 に答える