3

私のロジックは、INSERTの前にテーブルのIDを知る必要があります(挿入中にIDを手動で設定します)。このIDを使用するロジックは複数のサーバー上にあるため、mysqlにIDを作成させることは良い考えかもしれませんが、私が書いた関数はアトミックではないため、高負荷で呼び出すと、一意ではなく同一の番号が返されます。

CREATE FUNCTION `generate_document_log_id`() RETURNS BIGINT(16)
BEGIN
    DECLARE R_ID BIGINT(16);
    UPDATE document_log_sequence SET id = id + 1;
    SELECT id INTO R_ID FROM document_log_sequence;
    RETURN R_ID;
END

最後のIDを格納し、新しいIDごとにインクリメントするために、1つの列「id」を持つテーブル「document_log_sequence」を使用しています。たぶん解決策はこれからは程遠いですが、私にはこれ以上のアイデアはありません。

説明するのを忘れました。データベースサーバーは1つだけで、クライアントの数はn個です。上記の関数は(一種の)スレッドセーフではありません。

4

3 に答える 3

1

参考までに、データベース サーバーが 1 つしかない場合、これにより、次に挿入される ID の値が得られます。

SELECT AUTO_INCREMENT
FROM information_schema.TABLES
WHERE TABLE_NAME = 'my_table'
AND TABLE_SCHEMA = 'my_schema';

(編集済み-質問を誤解しました)

于 2011-06-14T13:22:06.967 に答える
1

インターリーブされたIDの戦略を使用できます

各サーバーには 0 から n までの番号が付けられ、n ずつステップするシーケンスにサーバー番号が追加されます。1 つの実装はAUTO_INCREMENT、ID 生成用のテーブルを用意し、その ID を次のような関数で使用することです。

CREATE TABLE ID_CREATOR (ID INT AUTO_INCREMENT PRIMARY KEY);

3 つのサーバーがあり、このサーバーがサーバー番号 1 であると仮定すると、この関数は各サーバーに一意の値を与えます。

CREATE FUNCTION generate_document_log_id() RETURNS INT
BEGIN
    DECLARE NUMBER_OF_SERVERS INT DEFAULT 3; -- Or read from some table
    DECLARE THIS_SERVER_ID INT DEFAULT 1; -- Or read from some table. Must be less than NUMBER_OF_SERVERS
    INSERT INTO ID_CREATOR VALUES (); -- This creates the next id
    RETURN LAST_INSERT_ID() * NUMBER_OF_SERVERS + THIS_SERVER_ID;  -- Unique numbers that interleave each other
END
于 2011-06-14T22:36:26.697 に答える
0

いくつかのオプションがあります

1) 16 バイト (128 ビット) のキーである 1 つの UUID を使用できます。この戦略は、n 個のサーバー データベース間でも機能します。

uuid() を選択します。(もちろん.. UUID をプレーン テキストで格納するにはフィールド CHAR(32) が必要です。MySQL にはしばらくの間 GUIID (128 ビット) 型のフィールドがありません)

私はストアド関数を使用するように衣装を着ています。これは私のバージョンの1つです:

BEGIN
DECLARE str_uuid varchar(32);
DECLARE cur1 CURSOR FOR select replace (o.oid, '-', '') from (select lower(UUID()) as oid) as o;
open cur1;
fetch cur1 into str_uuid;
close cur1;
return str_uuid;
END

2) INT または BIGINT を使用できますが、この戦略は同じデータベース サーバーでのみ機能します。

フィールド my_last_id、dt_hr_id (my_last_id は AUTOINCREMENT) を持つテーブルを考えてみましょう。

  • INSERT INTO YourTable (dt_hr_id) 値 (NOW());
  • SELECT LAS_INSERT_ID(); (この場合の SELECT は、所有者接続内で発生するため、常に機能します)

分離された接続を閉じます。

これはストアド プロシージャ/ストアド関数内で実行できますが、MySQL は同じ接続で複数のトランザクションをサポートしていないことを知っておく必要があるため、分離された接続内で実行する必要があります。

于 2013-03-28T16:01:54.250 に答える