当我们在做项目的时候经常会遇到这样一个问题,当有两个人A和B同时打开了同一条数据并且A和B都不知道对方也在编辑这条记录,之后相继保存成功了这笔数据。A和B都会觉得下次都出来的数据是自己刚才保存的数据,实际上,数据库中只保存了最后一个人提交的数据(先提交的数据会被后提交的覆盖),这样就照成了数据库中与操作者认为的不一致。
所以为了避免像A和B这样的操作冲突,我们模拟了一种锁的形式来操作,就是在数据库字段中新增一个栏位来记录数据由谁在编辑不允许编辑是否要强制夺回编辑的权利,但是这样的操作会比较麻烦,由于这种冲突的并发情况相对来说会比较少见,投入较大的精力在上面不值得,所以这边我们又想到了用SQL的timestamp这个时间戳的来轻松的实现避免冲突。
简单说一下,timestamp 主要是记录该行的最后修改时间戳,注意,这个时间戳是不可以转换为时间的,只能标注该行修改了相当于给该行做了一个版本号的机制。这个时间戳是系统自动生成的唯一二进制数字的数据类型。存储大小为 8 个字节。 timestamp 数据类型只是递增的数字,不保留日期或时间。 若要记录日期或时间,请使用 datetime 数据类型。每个数据库都有一个计数器。当然可以看出对行的任何更新都会更改 timestamp 值,从而更改键值。 如果该列属于主键,那么旧的键值将无效,进而引用该旧值的外键也将不再有效。 如果该表在动态游标中引用,则所有更新均会更改游标中行的位置。 如果该列属于索引键,则对数据行的所有更新还将导致索引更新。使用某一行中的 timestamp 列可以很容易地确定该行中的任何值自上次读取以后是否发生了更改。 如果对行进行了更改,就会更新该时间戳值。 如果没有对行进行更改,则该时间戳值将与以前读取该行时的时间戳值一致。 若要返回数据库的当前时间戳值,请使用 @@DBTS。timestamp不可为空的timestamp 列在语义上等同于 binary(8) 列。 可为空的 timestamp 列在语义上等同于 varbinary(8) 列。
操作如下:
- 当然要在表中添加一个栏位类型为timestamp类型的(sql时间戳)
- 在编辑数据页面做一个隐藏域来记录这个这个时间戳的值
- 就是在数据库中进行进行对读取出去的时间戳进行对比。==》'更新失败,可能是原记录不存在,或者更新冲突
举个例子 :
CREATE TABLE temp(t VARCHAR(10),Ts TIMESTAMP) INSERT INTO temp(t) VALUES( 'abc') DECLARE @ts TIMESTAMP SELECT @ts=Ts FROM temp WHERE t='abc' --事务A: WAITFOR DELAY '00:00:15' UPDATE temp SET t='xy1z' WHERE Ts=@ts --事务B: UPDATE temp SET t='aaa' WHERE Ts=@ts事务A在执行完毕后会发现并没有将'aaa'给抹去,这样就防止了丢失更新的现象。