MS проблема точности даты и времени SQL

У меня есть ситуация, где два человека могли бы работать над тем же порядком (сохраненный в базе данных SQL MS) от двух различных компьютеров. Для предотвращения потери данных в случае, где можно было бы сохранить его копию порядка сначала и затем немного позже, второе сохранит его копию и перезапишет первое, я добавил проверку по сравнению с lastSaved полем (дата и время) перед сохранением.

Код примерно походит на это:

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 Studio, databaseOrder. LastSaved и localOrderCopy. LastSaved, кажется, имеют то же значение, но выглядя ближе они несколько раз отличаются несколькими миллисекундами.

Я нашел эту статью с коротким уведомлением на точности миллисекунды для даты и времени в SQL:

Другая проблема состоит в том, что SQL Server снабжает ДАТУ И ВРЕМЯ точностью 3,33 миллисекунд (0. 00333 секунды).

Решение, о котором я мог думать для этой проблемы, состоит в том, чтобы сравнить два datetimes и считать их равными, если они отличаются меньше, чем говорить 10 миллисекунд.

Мой вопрос Вам затем: там какие-либо лучшие/более безопасные пути состоят в том, чтобы сравнить два значения даты и времени в MS SQL, чтобы видеть, являются ли они точно тем же?

6
задан Julian 12 April 2010 в 08:10
поделиться

5 ответов

Я знаю, что вы сказали, что не можете изменить тип, но если это необходимо только для поддержания совместимости и использования 2008 года, вы можете изменить поле lastSaved на DATETIME2 (т.е. полностью совместим с DATETIME ) и использует SYSDATETIME () , оба из которых имеют гораздо большую точность.

6
ответ дан 10 December 2019 в 02:44
поделиться

Пока вы находитесь в SQL 2005 и ранее, проблема точности всегда будет присутствовать, никогда не будет точнее 1/300 секунды, или 3,33 мс.

Независимо от недостатка точности вы программируете несовершенное состояние гонки, когда оба пользователя могут записывать в базу данных в быстрой последовательности, но оба будут считаться успешными. Отсутствие точности увеличивает вероятность того, что это произойдет, если только проверка и последующая запись происходят в течение тех же 3-4 мс.

Любая попытка проверки с последующей записью страдает от этой проблемы, и вам придется либо принять последствия оптимистической блокировки, либо изменить блокировку на пессимистическую, либо реализовать какую-то стратегию типа семафора для правильной обработки блокировки.

1
ответ дан 10 December 2019 в 02:44
поделиться

Вы можете использовать поле временной метки для проверки даты последнего редактирования, а не поле времени? (В SQL 2008 это теперь RowVersion)

0
ответ дан 10 December 2019 в 02:44
поделиться

Вы должны убедиться, что ваши временные точности совпадают - в основном это можно сделать, имея правильную логику на стороне C #, чтобы фактически снизить точность при является встроенным в объекте DateTime - в основном сделайте так, чтобы у вас были, например, временные метки всегда в секундах, а не ниже, на всех уровнях.

Если вы сделаете это правильно, отметки времени на всех уровнях будут немедленно сопоставимы.

0
ответ дан 10 December 2019 в 02:44
поделиться

Вы можете добавить поле целочисленной версии в таблицу заказов. Каждый раз, когда пользователь сохраняет заказ, вы увеличиваете ревизию на единицу. Затем легко проверить, изменил ли кто-то заказ или пользователь, который хочет сохранить заказ, находится на последней версии.

2
ответ дан 10 December 2019 в 02:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: