Как я могу получить транзакции SQL Server использовать блокировки уровня записи?

StackOverflow https://stackoverflow.com/questions/2646439

Вопрос

У нас есть приложение, которое было первоначально написано в качестве приложения для рабочего стола, Lo эти много лет назад. Он начинает транзакцию всякий раз, когда вы открываете экран редактирования, и комбинируете, если вы нажимаете OK, или откатываетесь назад, если вы нажмете «Отмена». Это работало в порядке для настольного приложения, но теперь мы пытаемся перейти к серверу ADO.NET и SQL, а длинные операции являются проблематичными.

Я обнаружил, что у нас будет проблема, когда множественные пользователи все пытаются редактировать (разные подмножества) того же стола одновременно. В нашей старой базе данных транзакция каждого пользователя приобретает блокировки уровня записи до каждой записи, которую они изменяли во время их транзакции; Поскольку разные пользователи редактировали разные записи, каждый получает свои собственные замки и все работает. Но на SQL Server, как только один пользователь редактирует запись в транзакции, SQL Server, кажется, получает блокировку на весь стол. Когда второй пользователь пытается редактировать другую запись в той же таблице, приложение второго пользователя просто блокируется, потому что блоки SQLConnection до того, как первый пользователь не совершит или не откатывает назад.

Я знаю, что длительные операции плохие, и я знаю, что Лучший Решение было бы изменение этих экранов так, чтобы они больше не держали транзакции открытыми в течение длительного времени. Но поскольку это будет означать некоторые инвазивные и рискованные изменения, я также хочу исследовать, есть ли способ получить этот код и запустить как есть, просто так я знаю, что есть мои варианты.

Как я могу получить две разные транзакции пользователей на SQL Server для блокировки отдельных записей вместо всей таблицы?

Вот приложение быстрого и грязного консоли, которое иллюстрирует проблему. Я создал базу данных под названием «TEST1», с одной таблицей называемыми «значениями», которые просто имеют идентификатор (INT) и столбцы Value (Nvarchar). Если вы запускаете приложение, он просит модифицировать идентификатор, запускает транзакцию, модифицирует эту запись, а затем оставляет транзакцию открыть, пока вы не нажмете ввод. Я хочу быть в состоянии

  1. Запустите программу и скажи, чтобы обновить ID 1;
  2. Пусть он получает свою транзакцию и изменить запись;
  3. Начните вторую копию программы и сообщите об этом, чтобы обновить ID 2;
  4. Можно ли обновить (и совершать), а транзакция первого приложения все еще открыта.

В настоящее время он замерзает на шаге 4, пока не вернусь к первой копии приложения и закрою его или нажмите Enter, чтобы он совершает. Вызов в команду.executenonquery Blocks до закрытия первого соединения.

public static void Main()
{
    Console.Write("ID to update: ");
    var id = int.Parse(Console.ReadLine());
    Console.WriteLine("Starting transaction");
    using (var scope = new TransactionScope())
    using (var connection = new SqlConnection(@"Data Source=localhost\sqlexpress;Initial Catalog=test1;Integrated Security=True"))
    {
        connection.Open();
        var command = connection.CreateCommand();
        command.CommandText = "UPDATE [Values] SET Value = 'Value' WHERE ID = " + id;
        Console.WriteLine("Updating record");
        command.ExecuteNonQuery();
        Console.Write("Press ENTER to end transaction: ");
        Console.ReadLine();
        scope.Complete();
    }
}

Вот некоторые вещи, которые я уже пробовал, без изменения в поведении:

  • Изменение уровня изоляции транзакций на «Читайте незафиксированные»
  • Указание «с (RowLock)» в оператор обновления
Это было полезно?

Решение

Просто проверяю, но у вас есть основной ключ или уникальный индекс в столбце ID?

Другие советы

Посмотрите на оптимистичный по сравнению с пессимистичным замком.

Редактировать: Предыдущая статья связана с Classic Ado ... Извините.

http://msdn.microsoft.com/en-us/library/cs6hb8k4(vs.71).aspx.

Вероятно, индекс был создан с блокировками строки, установленным на «OFF».
«С (Rowlock)» в запросе не повлияло бы в этом случае.

Вы можете включить их снова с Изменять индекс, например:

ALTER INDEX [PK_Values] ON [Values] SET (ALLOW_ROW_LOCKS = ON)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top