我遇到的情况是,两个人可能在两台不同的计算机上按相同的顺序工作(存储在MS数据库中)。为了防止数据丢失,在这样的情况下,一个人将首先保存他的订单副本,然后第二个将保存他的副本并覆盖第一个,我在保存之前添加了一个针对lastSaved字段(datetime)的检查。
代码大致如下所示:
private bool orderIsChangedByOtherUser(Order localOrderCopy)
{
    // Look up fresh version of the order from the DB
    Order databaseOrder = orderService.GetByOrderId(localOrderCopy.Id);
    if (databaseOrder != null &&
        databaseOrder.LastSaved > localOrderCopy.LastSaved)
    {
        return true;
    }
    else
    {
        return false;
    }
}这在大多数情况下都是可行的,但我发现了一个小错误。
如果orderIsChangedByOtherUser返回false,则本地副本将使其lastSaved更新到当前时间,然后持久化到数据库。lastSaved在本地副本和DB中的值现在应该是相同的。但是,如果orderIsChangedByOtherUser再次运行,它有时会返回true,即使没有其他用户对DB进行更改。
在Visual中调试时,databaseOrder.LastSaved和localOrderCopy.LastSaved的值似乎是相同的,但仔细看时,它们有时相差几毫秒。
我发现这篇文章在SQL中对datetime的毫秒精度做了一个简短的说明:
另一个问题是Server存储日期时间的精度为3.33毫秒(0毫秒)。00333秒)。
对于这个问题,我能想到的解决方案是比较这两个日期时间,如果它们的差值小于10毫秒,则将它们视为相等。
那么,我对您的问题是:是否有更好/更安全的方法来比较MS中的两个日期时间值,看看它们是否完全相同?
发布于 2010-04-12 10:01:57
我知道您说过不能更改类型,但是如果这只是为了维护兼容性&使用2008年,您可以将lastSaved字段更改为DATETIME2 (与DATETIME完全兼容),并使用SYSDATETIME(),两者都具有更高的精度。
发布于 2010-04-12 08:32:07
可以向order表中添加整数修订字段。每次用户保存订单时,您都会将修订增加一次。然后很容易检查某人是否更改了订单,或者想保存订单的用户是否在最新的版本中。
发布于 2010-04-12 09:12:17
虽然您在SQL 2005和之前的准确性问题将始终存在,从来没有比1/300秒,或3.33ms更准确。
尽管缺乏准确性,但您正在编写一种有缺陷的竞赛条件,在这种情况下,两个用户仍然可以快速地写入数据库,但两者都被认为是成功的。准确性的缺乏增加了发生这种情况的机会,只要检查和后续写入发生在相同的3-4 ms内。
任何在写之后进行检查的尝试都会遇到这个问题,您要么必须接受乐观锁定的后果,要么将锁定更改为pessemistic,要么实现某种形式的信号量类型策略来正确处理锁定。
https://stackoverflow.com/questions/2620627
复制相似问题