SQL Server Rowversion/Timestamp-比較
-
11-10-2019 - |
質問
私はaの値自体を知っています RowVersion
行が更新されるたびに変更されることを除いて、列はそれ自体に有用ではありません。しかし、私はそれらが相対的な(不平等)比較に役立つかどうか疑問に思っていました。
テーブルがある場合 RowVersion
列は、次のいずれかです。
- 同時に発生するすべての更新(同じ更新ステートメントまたは同じトランザクションのいずれか)が同じ値を持っていますか
RowVersion
桁? - 「A」を更新し、その後に更新「B」が続くと、更新「B」に関係する行は、更新「A」に伴う行よりも高い値がありますか?
ありがとう。
解決
各データベースにはカウンターがあります 挿入または更新ごとに増加します を含むテーブルで実行される操作 rowversion
データベース内の列。このカウンターはデータベースです rowversion
. 。これにより、データベース内の相対的な時間を追跡しますが、クロックに関連付けられる実際の時間ではありません。 毎回 それ 行 とともに rowversion
桁 変更または挿入されます, 、 増加 データベース rowversion
価値 に挿入されます rowversion
桁。
http://msdn.microsoft.com/en-us/library/ms182776.aspx
- 私が理解している限り、システムで実際に同時に何も起こりません。これはすべてを意味します
rowversion
Sは一意でなければなりません。同じテーブル内で複製が許可されていれば、それらは効果的に役に立たないと言います。また、信用を与えますrowversion
重複していないのは、違反を引き起こすためではなく、外国のキーの問題を引き起こすため、プライマリキーとしてそれらを使用しないというMSDNの姿勢です。 - MSDNによると、「Rowversionデータ型は単なる増加数です...」では、はい、後で大きくなります。
の質問に いくら それは増加します、MSDNは次のように述べています。rowversion
]データベース内の相対時間を追跡します。これは、それが流体の整数の増加ではなく、時間に基づいていることを示しています。しかし、この「時間」はいつを明らかにしません まさに, 、むしろいつ 他の行に関連して 行が挿入/変更されました。
他のヒント
いくつかの追加情報。 RowversionはBigintにうまく変換されるため、デバッグ時により適切な読み取り可能な出力を表示できます。
CREATE TABLE [dbo].[T1](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Value] [nvarchar](50) NULL,
[RowVer] [timestamp] NOT NULL
)
insert into t1 ([value]) values ('a')
insert into t1 ([value]) values ('b')
insert into t1 ([value]) values ('c')
select Id, Value,CONVERT(bigint,rowver)as RowVer from t1
update t1 set [value] = 'x' where id = 3
select Id, Value,CONVERT(bigint,rowver)as RowVer from t1
update t1 set [value] = 'y'
select Id, Value,CONVERT(bigint,rowver)as RowVer from t1
Id Value RowVer
1 a 2037
2 b 2038
3 c 2039
Id Value RowVer
1 a 2037
2 b 2038
3 x 2040
Id Value RowVer
1 y 2041
2 y 2042
3 y 2043
私はこれを使って何かを整理しようとして何年も費やしました - 特定のシーケンス番号の後に更新された列を要求するために。タイムスタンプは、実際にはシーケンス番号にすぎません。C#がBitConverter.toint64のように機能する場合も、ビッグエンディアンです。
私はテーブルにDBビューを作成することになりました。エイリアス列「Sequenceno」を使用してデータが必要です
SELECT ID, CONVERT(bigint, Timestamp) AS SequenceNo
FROM dbo.[User]
C#コードは、最初に通常のテーブルと同じようにビュー(つまり、userv)を見ます
次に、私のlinqでビューと親のテーブルに参加して、シーケンス番号と比較できます
var users = (from u in context.GetTable<User>()
join uv in context.GetTable<UserV>() on u.ID equals uv.ID
where mysequenceNo < uv.SequenceNo
orderby uv.SequenceNo
select u).ToList();
私が望むものを取得するために - すべてのエントリは最後にチェックしたときから変更されました。
タイムスタンプのデータ型は悪だと思う理由は何ですか?データ型は、並行性チェックに非常に役立ちます。 LINQ-to-SQLは、このまさに目的のためにこのデータ型を使用します。
あなたの質問への答え:
1)いいえ。この値は、行が更新されるたびに更新されます。行を更新している場合、各更新はタイムスタンプの値を増加させます。もちろん、「同時に発生する」という更新が本当にそうではないことを理解しています。それらはまだ一度に1つだけ発生します。
2)はい。
メモとして、 timestamp
SQL Server 2008以降では非推奨です。 rowversion
代わりに使用する必要があります。
から このページ MSDNについて:
タイムスタンプ 構文は非推奨です。この機能は、Microsoft SQL Serverの将来のバージョンで削除されます。新しい開発作業でこの機能を使用しないようにし、現在この機能を使用しているアプリケーションを変更することを計画してください。
Rowversionは、SQLの「理想主義的な」アプローチの1つを破ります - 更新ステートメントは単一の原子作用であり、まるですべての更新(連続内のすべての列、およびテーブル内のすべての行が)のように動作するかのように動作します。同時"。しかし、この場合、Rowversionを使用すると、1つの行が別の行とはわずかに異なる時間で更新されたと判断することができます。
行が更新される順序(単一の更新ステートメントによって)が保証されていないことに注意してください - 偶然には、テーブルのクラスター化されたキーと同じ順序に従うことがありますが、私はそれが真実であるとは考えていません。
質問の一部に答えるには:MSDNによると、次の値が重複することがあります。
重複したRowversion値は、Selectを使用してRowversion列が選択リストにあるステートメントに生成できます。この方法でRowversionを使用することはお勧めしません。
すべてのデータベースには、データベースで行われるすべてのデータ変更で1つずつ増加するカウンターがあります。影響を受ける(更新/挿入)行を含むテーブルにタイムスタンプ/Rowversion列が含まれている場合、データベースの現在のカウンター値は、更新/挿入されたレコードの列に保存されます。