皆さん、こんにちは。 SQL Server/Windows Azure SQL Database サポートチーム の高原です。
今回は、SQL Server / Windows Azure SQL Database (以下 WASD) の何れでも使用可能な IDENTITY プロパティの動作について説明します。
[IDENTITY プロパティとは]
IDENTITY プロパティをテーブル列に指定した場合、追加した列では、行が追加 (Insert) される毎に、指定された増分の値を基に、自動的に ID 番号を採番することが可能になります。そのため、ID を自動的に採番したい場合、IDENTITY プロパティを使用することにより、番号を採番する仕組みをアプリケーション側で実装する手間を省くことができます。
[IDENTITY プロパティの制限事項]
IDENTITY プロパティは 非常に便利な機能なのですが、次の点が保証されていません。
1) 連続された ID 値が採番されることを保証していない。
パフォーマンス上の理由から 採番される ID 値がキャッシュ上に保持されているため、サーバーの再起動や、データベースの再起動が発生した場合、キャッシュ上に保持された ID 値が失われ、次回 行挿入時に、前回 挿入された値から非連続的な ID が生成される場合があります。
また、1つのトランザクション内で連続した値が必ず採番されることも保証されていないため、1 つのトランザクション内で連続した値を必ず採番する必要がある場合は、他のトランザクションから列の挿入が行われないよう、該当テーブルに対して、排他ロックを獲得するなどの対策が必要です。
2) 値の一意性を保証していない
値の一意性を保証していないため、ID 列の一意性を保証させるために、PRIMARY KEY 制約、UNIQUE 制約、または UNIQUE インデックスを使用して、一意性を強制する必要があります。
3) 値が再利用されることを保証していない
特定の挿入クエリが失敗 もしくは ロールバックされた場合、取得された ID 値は失われ、再度 生成されることはありません。
[補足]
特にお問い合わせの多い 1) 連続された ID 値が採番されることを保証していない。について補足します。
パフォーマンス上の理由から 採番される ID 値がキャッシュ上に保持されることを記載しましたが、例えば int 型の列に IDENTITY プロパティを指定した場合、キャッシュ上には 1000個の ID 値がキャッシュされます。(例: 1001 – 2000 など)
そのため、1005 までしか採番されていない状況時に、サーバーの再起動などによりキャッシュがクリアされると、次回の採番される値が 2001 からとなり、ID 値の連続性が損なわれます。
また、この動作は、SQL Server 2012 以降のバージョン、及び WASD で発生しうる現象となります。
※ SQL Server 2008 R2 以前のバージョンでは、ID 値をキャッシュしていないため、キャッシュ上の ID 値がクリアされる現象は発生しません。
WASD の場合、更新プログラムの適用やマシンの健全性を保つ目的で、内部的に フェールオーバーが行われるため、ID 値の連続性が損なわれる可能性があります。
※ その他 データ型については、表1 を参照ください。
データ型 | キャッシュされる ID 値の数 | |
Tinyint | 10 | |
smallint | 100 | |
Int | 1,000 | |
Bigint | 10,000 | |
Decimal/numeric |
| |
| 有効桁数 (Precision) < 2 | 5 |
Precision < 4 | 10 | |
Precision < 6 | 100 | |
Precision < 8 | 1,000 | |
Precision >= 8 | 10,000 |
表1 : IDENTITY プロパティ使用時にキャッシュされる ID 値の数
[参考情報]
IDENTITY (プロパティ) (Transact-SQL)
※ 本Blogの内容は、2014年4月 現在の内容となっております