一直對時間戳這個概念比較模糊,相信有很多朋友也都會誤認為:時間戳是一個時間字段,每次增加資料時,填入目前的時間值。其實這誤導了很多朋友。
1.基本概念
時間戳:資料庫中自動生成的唯一二進制數字,與時間和日期無關的, 通常用作給表行加版本戳的機制。存儲大小為 8個位元組。
每個資料庫都有一個計數器,當對資料庫中包含 timestamp 列的表執行插入或更新操作時,該計數器值就會增加。該計數器是資料庫時間戳。這可以跟蹤資料庫内的相對時間,而不是時鐘相關聯的實際時間。一個表隻能有一個 timestamp 列。每次修改或插入包含 timestamp 列的行時,就會在 timestamp 列中插入增量資料庫時間戳值。這一屬性使 timestamp 列不适合作為鍵使用,尤其是不能作為主鍵使用。對行的任何更新都會更改 timestamp 值,進而更改鍵值。如果該列屬于主鍵,那麼舊的鍵值将無效,進而引用該舊值的外鍵也将不再有效。如果該表在動态遊标中引用,則所有更新均會更改遊标中行的位置。如果該列屬于索引鍵,則對資料行的所有更新還将導緻索引更新。
使用某一行中的 timestamp 列可以很容易地确定該行中的任何值自上次讀取以後是否發生了更改。如果對行進行了更改,就會更新該時間戳值。如果沒有對行進行更改,則該時間戳值将與以前讀取該行時的時間戳值一緻。若要傳回資料庫的目前時間戳值,請使用 @@DBTS。
2.時間戳的作用
在控制并發時起到作用:
使用者A/B同時打開某條記錄開始編輯,儲存是可以判斷時間戳,因為記錄每次被更新時,系統都會自動維護時間戳,是以如果儲存時發現取出來的時間戳與資料庫中的時間戳不相等,說明在這個過程中記錄被更新過,這樣的話可以防止别人的更新被覆寫。
3.時間戳的應用
簡單說一下,timestamp
主要是記錄該行的最後修改時間戳,注意,這個時間戳是不可以轉換為時間的,隻能标注該行修改了。
有什麼用呢?通常是用在資料增量更新方面,比如說,我從該表複制資料到另外一個表,但是如果我想隻複制更新過的,那麼從最後一次更新的時候,記錄最大的timestamp的值,然後在目前更新的時候,隻要where條件找出大于最後一次更新的
timestamp 值的所有行。然後抽取到更新過的資料,進行複制到另外一個伺服器,這就是增量更新用到的。
4.在SQL中的應用例子
(微軟的建議 -- timestamp 文法已被取代,在 DDL 語句,請盡量使用 rowversion 而不是 timestamp。未來的
Microsoft SQL Server 版本将移除這項功能。
<dl></dl>
<dd></dd>
RowsVersion就是timestamp
丢失更新的解決方法
丢失更新概念:當使用者同時修改一行資料,他們先讀取資料,放在前端進行修改,當修改後,再送出資料,這樣最後送出的資料會覆寫先前送出的資料,
這樣就造成了丢失更新。
長話短說,介紹防止丢失更新的方法:
使用RowsVersion時間戳。
每次更新的時候,mssql都會自動的更新rowversion的值,若一行在讀前與更新前的值前後不一緻,就說明有其他的事務更新了此列,這樣就可以不更新此列,
進而防止了丢失更新的情況。
例子 :
declare table tmp(a varchar(10),b rowsversion)
insert into tmp(a) values( 'abc')
事務A:
declare @rv rowversion
select @rv=b from tmp where a='abc'
waitfor delay '00:00:05'
update tmp set a='xyz' where b=@rv
事務B:
update tmp set a='aaa' where b=@rv
事務A在執行完畢後會發現并沒有将'aaa'給抹去,這樣就防止了丢失更新的現象。
注意:
在使用其中的 SELECT 清單中具有 timestamp 列的 SELECT INTO
或者Insert Select 語句時,可能會生成重複的時間戳值。建議不要以這種方式使用 timestamp。

注意
通過使用在其 SELECT 清單中包含了 rowversion 列的 SELECT INTO 語句,可以生成重複的 rowversion 值。
建議不要以這種方式使用 rowversion。
添加資料 如高并發的情況下 時間戳會相同嗎
是肯定會相同的,如果你的并發在一秒内有多條資訊插入,那麼時間戳肯定會相同