2011-01-13 12 views
3

この問題が起こる可能性は、私には起こり得る問題のために私にはほとんど起こりそうにないようですが、私は質問していました...自動インクリメントIDはコミット時にトランザクションの中間値から変更されることはありますか?

オートインクリメントIDが関与し、割り当てられた。 COMMITの前に、関係するコードは、後で参照できるように、割り当てられたIDのコピーをキャッシュします。その後、トランザクションがコミットされます。

直接クライアントの介入(レコードの削除または変更)がないと仮定すると、キャッシュされたIDが間違っているため、COMMITの直後にID値を自動的に変更するデータベースや状況がありますか? ID中間トランザクションをキャッシュするのはいつでも安全ですか?

私は、このような状況が起きると想像することができますが、RDBMSの実装によっては、gapless値と時間依存型の自動インクリメント値が必要であると判断される場合があります。この仮説的なケースでは、別のトランザクション(または他のギャップ・コッシャー)でのID割り当て後のロールバックによって生じるギャップを埋めるために、IDのいくつかの魔法のシ​​ャッフルが行われるかもしれないと想像することができます。これは、キャッシュされた値を無効にします。

誰かがこのような実装や他のキャッシュキラーを知っていますか?

答えて

4

生成されたid値の実装では、通常、短いアトミック操作でカウンタ値がインクリメントされます。この値は要求側のトランザクションで使用され、そのトランザクションがロールバックされても、予約済みの値は決して空き値のプールに返されません。だからこの光の中では、私は説明された状況が非常に可能性が高いとは思わない。また、pl/sql型のプログラムでは、子テーブルに他の従属行を挿入するためには、実際に生成された値が必要です。

時間順不同のid値を求めている人は、自動インクリメント/代理キーの唯一の目的は行の人為的な識別を作成することです。行の作成順序を決定することとは関係がありません。たとえば、作成タイムスタンプを使用してこれを行う方法がはるかに優れています。

+0

+1私は自問自答者の使用について絶対に正しいと思うのですが...技術的には、値を使って作成順序を決めるのであれば、技術的には代理キーではありません:D – Matthew

+0

'InnoDB'では、 MySQLが使用するトランザクショナルストレージエンジンであるautoincremented idsを再利用することができます。最も高い 'id'を持つレコードが削除され、サーバが再起動された場合、テーブルへの次の挿入は同じ' id'になります。 – Quassnoi

1

PostgreSQLDEFERREDCOMMITのデータを変更するトリガーをサポートします。

CREATE TABLE test_autoinc (id BIGSERIAL); 

CREATE TABLE test_other (id BIGSERIAL); 

CREATE FUNCTION prc_update_autoinc() 
RETURNS TRIGGER 
AS 
$$ 
BEGIN 
     UPDATE test_autoinc 
     SET  id = id + 10; 
     RETURN NEW; 
END; 
$$ 
LANGUAGE 'plpgsql'; 

CREATE CONSTRAINT TRIGGER 
     trg_other_ai 
AFTER INSERT 
ON  test_other 
DEFERRABLE 
INITIALLY DEFERRED 
FOR EACH ROW 
EXECUTE PROCEDURE prc_update_autoinc(); 

BEGIN TRANSACTION; 

INSERT 
INTO test_autoinc 
DEFAULT VALUES; 

INSERT 
INTO test_other 
DEFAULT VALUES; 

SELECT * 
FROM test_autoinc; 

COMMIT; 

SELECT * 
FROM test_autoinc; 

SELECTCOMMIT前右)は(右COMMIT後)第二つ11を返し、1を返します。

+0

Thx ...興味深い例です。直接的な介入であっても、起こる可能性がある場合を示すため+1。 – Russ

関連する問題