Столбец версии SQL-сервера обновляется больше, чем должно - PullRequest
0 голосов
/ 06 декабря 2009

Мы используем NHibernate, чтобы обновить таблицу счетов с балансом для пользователя. Один контрольный пример, который блокирует нас:


var s = NHibernateHelper.OpenSession();
var q = s.CreateQuery("Update Account set Balance=? where UserId=? and Version=?");
var acc = s.Load(1);
ITransaction tx = null;
for (int j = 0; j < NUM_UPDATES; j++)
{
    int rowcount = 0;
    var tx = s.BeginTransaction();
    do
    {
        s.Refresh(acc);
        q.SetDouble(0, acc.Balance + _amount).SetInt32(1, 1).SetBinary(2, acc.Version);
        rowcount = q.ExecuteUpdate();
    } while (rowcount <= 0);
    tx.Commit();
}

этот код выполняется как в одном потоке, так и в нескольких потоках одновременно (следовательно, управление версиями). он выполняется правильно, но - номер версии увеличивается на число, которое больше фактического количества обновлений (NUM_UPDATES) на некоторое значение.

например. если мы делаем 16 обновлений, номер версии увеличивается на 16 или 17. Если мы делаем 1000 обновлений, номер версии увеличивается на 1004.

Если 16 потоков выполняют один и тот же код (на 4-ядерном компьютере) с 1000 обновлений в каждом, то мы, очевидно, получим много попыток, и версия будет увеличена на 16064 (1004 * 16).

Есть идеи, что вызвало это? Есть ли причина для тревоги?

Ответы [ 3 ]

4 голосов
/ 06 декабря 2009

Если столбец версии имеет тип timestamp или rowversion, то он обновляется с использованием глобального счетчика. Этот глобальный счетчик увеличивается всякий раз, когда любая строка в любой таблице, содержащей столбец версии строки, вставляется или обновляется. Так что это не повод для беспокойства. Он просто отражает другую активность в базе данных.

0 голосов
/ 06 декабря 2009

Поскольку вы создаете свои собственные запросы, вы можете атомарно увеличивать столбец в ОБНОВЛЕНИИ:

UPDATE Account SET Balance = Balance + @amount WHERE UserId = @uid

Это также сэкономит накладные расходы на создание и совершение отдельной транзакции.

0 голосов
/ 06 декабря 2009

Читать здесь Подробнее о rowvwersion (timestamp) в SQL-сервере. Что нужно знать:

  • не имеет никакого отношения ко времени; кроме большего числа было сгенерировано позже.
  • Счетчик глобален для базы данных.
  • Это автоматически изменено, вы не меняете его.
  • Может использоваться в запросах для обнаружения изменения данных, во время синхронизации и т. Д.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...