2023年6月21日发(作者:)
开放式并发冲突检测的四种方法
由于在BugTiger中需要用到冲突检测,所以对冲突检测进行了学习,现总结了如下四种方法:
一.使用时间戳.
在数据库的表中添加一个时间戳列或版本列.时间戳列与对表内容的查询一起返回.当试图更新时,数据库中的时间戳值将与被修改行中的原始时间戳值进行比较.如果这两个值匹配,则执行更新,同时时间戳列被更新为当前时间以反映更新.如果这两个值不匹配,则发生开放式并发冲突.
示例
表结构(Method1):BugTimeStamp为时间戳列.
当用户取得数据时,将BugTimeStamp列也返回给用户.
SELECT BugID, BugType, BugTimeStampFROM Method1
当用户更新时BugTimeStamp作为条件进行比较.
UPDATE Method1
SET BugType = ‘b‘
WHERE (BugID = 1) AND (BugTimeStamp =
0x04B1) 更新时如果从上次读取数据到这次更新这段时间内已经被更改过了,条件显然是不成立了.因为每次更新记录时,timestamp 列中的值均会更新.
二.保留原始数据值的副本.
在查询数据库的数据时保留原始数据值的一个副本.在更新数据库时,检查数据库的当前值是否与原始值匹配.原始值保存在 DataSet 中,当更新数据库时,数据适配器可以使用该原始值执行开放式并发检查.
示例.
表结构(Method2)
UPDATE Tasks SET BugType = @ BugType WHERE
(BugID = @BugD) AND (BugType = @Original_BugType)
@Original_BugType 可以这样指定
(new
SqlParameter("@Original_BugType", , 10,
, false, 0, 0, " BugType ",
al, null));
三.多列确定原则(我自己命名的,) 可以通过一表中的最后更新时间(LastUpdateDate)和最后更新用户(LastUpdateUserID)来确定一条记录是否已经被其他用户修改.如果只用最后更新时间,还是会有冲突发现,虽然这样的概率比较低,因为DateTime的精确度为百分之三秒,在A用户取出后的足够短的时间内有B用户修改了数据,这时最后更新时间没有发生变化,但是数据有变化了,所以当A用户修改时实际上已经发生了冲突.使用最后更新用户(LastUpdateUserID)后,还是上述情况,由于LastUpdateUserID已经更改,只要A用户更新时同时检查最后更新时间(LastUpdateDate)和最后更新用户(LastUpdateUserID)就可以检查出冲突.
在这种方法里假设了同一用户在百分之三秒不可能进行两次更新.我觉得这样的假设在通常情况下是合理的.
示例:
表结构(Method3)
取数据
SELECT [BugID], [BugProject], [BugType],
[LastUpdateDate], [LastUserID] FROM [Method3] 更新数据时UPDATE [Method3]SET BugID =
@BugID, [BugProject] = @BugProject, [BugType] =
@BugType, [LastUpdateDate] = @LastUpdateDate ,
[LastUserID]= @LastUserID,WHERE [BugID]= @BugID ,
[LastUpdateDate]=@ OriginalLastUpdateDate ,
[LastUserID] = @OriginalLastUserID四.BINARY_CHECKSUM
SQL联机丛书上的解释:
在表中任一行上计算的 BINARY_CHECKSUM(*) 返回相同的值,只要随后没有修改行.BINARY_CHECKSUM(*) 将为大多数(但不是全部)行更改返回不同的值,并可用于检测大多数行修改.
这各方法有很大的局限性:
BINARY_CHECKSUM 在计算中忽略具有不可比数据类型的列.不可比数据类型是 text、ntext、image、cursor 以及基本类型为前 4 个数据类型之一的 sql_variant.
字符串的区域设置可能导致具有不同表示法的字符串进行等值比较.在区分大小写的服务器中,字符串"McCavity"和"Mccavity"的 BINARY_CHECKSUM 值不同.反之,在不区分大小写的服务器中,上述字符串的 CHECKSUM 返回相同的校验值. 示例.
表结构(Method4)取数据时把BINARY_CHECKSUM(*)也返回给用户SELECT [BugType], BINARY_CHECKSUM(*) AS
RowCheckSum
FROM [Method4]当用户修改数据时
UPDATE Method4
SET BugType = ‘b‘
WHERE (BugID = 1) AND (CHECKSUM(*) = @
RowCheckSum)
四种方式的比较
1. 优点:实现比较简单,timestamp 列中的值会更新.不足:要增加一个额外的字段.
2. 优点:可靠,不需要额外字段.不足:当字段较多时需要较多的参数.
3. 优点:和2相比,传递的参数较少.不足:使用的字段对系统不一定有存在的意义,如例子中的最后更新时间(LastUpdateDate)和最后更新用户(LastUpdateUserID)有时对系统不是必需的.
4. 优点:不需要额外字段,只需要一个参数.不足:有些数据类型不可比BINARY_CHECKSUM, 字符串的区域设置可能导致具有不同表示法的字符串进行等值比较. 只为大多数(但不是全部)行更改返回不同的值. (笔者注:不知道这个大多数是什么概率.)
参考文档
n 《数据层组件设计与数据传递》/20021112/
n hudan 的留言/archive/2005/08/05/#208605
n TaskVision
/Applications/?PageID=20&tabindex=8
n IssueVision
/Applications/?PageID=40&tabindex=8
n 《SQL Server 联机丛书》
n 《MSDN》
2023年6月21日发(作者:)
开放式并发冲突检测的四种方法
由于在BugTiger中需要用到冲突检测,所以对冲突检测进行了学习,现总结了如下四种方法:
一.使用时间戳.
在数据库的表中添加一个时间戳列或版本列.时间戳列与对表内容的查询一起返回.当试图更新时,数据库中的时间戳值将与被修改行中的原始时间戳值进行比较.如果这两个值匹配,则执行更新,同时时间戳列被更新为当前时间以反映更新.如果这两个值不匹配,则发生开放式并发冲突.
示例
表结构(Method1):BugTimeStamp为时间戳列.
当用户取得数据时,将BugTimeStamp列也返回给用户.
SELECT BugID, BugType, BugTimeStampFROM Method1
当用户更新时BugTimeStamp作为条件进行比较.
UPDATE Method1
SET BugType = ‘b‘
WHERE (BugID = 1) AND (BugTimeStamp =
0x04B1) 更新时如果从上次读取数据到这次更新这段时间内已经被更改过了,条件显然是不成立了.因为每次更新记录时,timestamp 列中的值均会更新.
二.保留原始数据值的副本.
在查询数据库的数据时保留原始数据值的一个副本.在更新数据库时,检查数据库的当前值是否与原始值匹配.原始值保存在 DataSet 中,当更新数据库时,数据适配器可以使用该原始值执行开放式并发检查.
示例.
表结构(Method2)
UPDATE Tasks SET BugType = @ BugType WHERE
(BugID = @BugD) AND (BugType = @Original_BugType)
@Original_BugType 可以这样指定
(new
SqlParameter("@Original_BugType", , 10,
, false, 0, 0, " BugType ",
al, null));
三.多列确定原则(我自己命名的,) 可以通过一表中的最后更新时间(LastUpdateDate)和最后更新用户(LastUpdateUserID)来确定一条记录是否已经被其他用户修改.如果只用最后更新时间,还是会有冲突发现,虽然这样的概率比较低,因为DateTime的精确度为百分之三秒,在A用户取出后的足够短的时间内有B用户修改了数据,这时最后更新时间没有发生变化,但是数据有变化了,所以当A用户修改时实际上已经发生了冲突.使用最后更新用户(LastUpdateUserID)后,还是上述情况,由于LastUpdateUserID已经更改,只要A用户更新时同时检查最后更新时间(LastUpdateDate)和最后更新用户(LastUpdateUserID)就可以检查出冲突.
在这种方法里假设了同一用户在百分之三秒不可能进行两次更新.我觉得这样的假设在通常情况下是合理的.
示例:
表结构(Method3)
取数据
SELECT [BugID], [BugProject], [BugType],
[LastUpdateDate], [LastUserID] FROM [Method3] 更新数据时UPDATE [Method3]SET BugID =
@BugID, [BugProject] = @BugProject, [BugType] =
@BugType, [LastUpdateDate] = @LastUpdateDate ,
[LastUserID]= @LastUserID,WHERE [BugID]= @BugID ,
[LastUpdateDate]=@ OriginalLastUpdateDate ,
[LastUserID] = @OriginalLastUserID四.BINARY_CHECKSUM
SQL联机丛书上的解释:
在表中任一行上计算的 BINARY_CHECKSUM(*) 返回相同的值,只要随后没有修改行.BINARY_CHECKSUM(*) 将为大多数(但不是全部)行更改返回不同的值,并可用于检测大多数行修改.
这各方法有很大的局限性:
BINARY_CHECKSUM 在计算中忽略具有不可比数据类型的列.不可比数据类型是 text、ntext、image、cursor 以及基本类型为前 4 个数据类型之一的 sql_variant.
字符串的区域设置可能导致具有不同表示法的字符串进行等值比较.在区分大小写的服务器中,字符串"McCavity"和"Mccavity"的 BINARY_CHECKSUM 值不同.反之,在不区分大小写的服务器中,上述字符串的 CHECKSUM 返回相同的校验值. 示例.
表结构(Method4)取数据时把BINARY_CHECKSUM(*)也返回给用户SELECT [BugType], BINARY_CHECKSUM(*) AS
RowCheckSum
FROM [Method4]当用户修改数据时
UPDATE Method4
SET BugType = ‘b‘
WHERE (BugID = 1) AND (CHECKSUM(*) = @
RowCheckSum)
四种方式的比较
1. 优点:实现比较简单,timestamp 列中的值会更新.不足:要增加一个额外的字段.
2. 优点:可靠,不需要额外字段.不足:当字段较多时需要较多的参数.
3. 优点:和2相比,传递的参数较少.不足:使用的字段对系统不一定有存在的意义,如例子中的最后更新时间(LastUpdateDate)和最后更新用户(LastUpdateUserID)有时对系统不是必需的.
4. 优点:不需要额外字段,只需要一个参数.不足:有些数据类型不可比BINARY_CHECKSUM, 字符串的区域设置可能导致具有不同表示法的字符串进行等值比较. 只为大多数(但不是全部)行更改返回不同的值. (笔者注:不知道这个大多数是什么概率.)
参考文档
n 《数据层组件设计与数据传递》/20021112/
n hudan 的留言/archive/2005/08/05/#208605
n TaskVision
/Applications/?PageID=20&tabindex=8
n IssueVision
/Applications/?PageID=40&tabindex=8
n 《SQL Server 联机丛书》
n 《MSDN》
发布评论