Как получить SQL-вставку и /или обновление, чтобы не блокировать всю таблицу на MS SQL Server

Очень новичок в работе с БД, поэтому оцените ваше терпение с помощью основного вопроса. Я запускаю SQL Server 2014 на своей локальной машине, и у меня есть небольшая таблица и основное клиентское приложение для тестирования различных подходов. Я получаю то, что кажется блокировкой таблицы во время обоих INSERT INTO и UPDATE. Клиент представляет собой приложение ASP.NET со следующим кодом:

OleDbConnection cn = new OleDbConnection("Provider=SQLNCLI11; server=localhost\\SQLEXPRESS; Database=<my db>; user id=<my uid>; password=<my pwd>");
cn.Open();
OleDbTransaction tn = cn.BeginTransaction();
OleDbCommand cmd = new OleDbCommand("INSERT INTO LAYOUTSv2 (LAYOUTS_name_t, LAYOUTS_enabled_b, LAYOUTS_data_m) VALUES ('name', '-1', 'data')", cn, tn);
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT SCOPE_IDENTITY()";
int newkey = Decimal.ToInt32((decimal)cmd.ExecuteScalar());
Console.WriteLine("Created index " + newkey);
Thread.Sleep(15000);
tn.Commit();
tn = cn.BeginTransaction();
cmd.CommandText = "UDPATE LAYOUTSv2 SET LAYOUTS_enabled_b='-3' WHERE LAYOUTS_key='" + newkey + "'";
cmd.Transaction = tn;
cmd.ExecuteNonQuery();
Console.WriteLine("updated row");
Thread.Sleep(15000);
tn.Rollback();
cn.Close();

Я запускаю этот код, затем из студии управления я запускаю SELECT * FROM LAYOUTSv2. В обоих случаях, когда клиентский поток приостанавливается (то есть до фиксации /откат), запрос SELECT зависает до тех пор, пока не произойдет фиксация /откат.

В таблице указано поле LAYOUTS_key, назначенное в качестве первичного ключа. В окне свойств он показывает, что он уникален и сгруппирован, причем блокировки страниц и блокировки строк разрешены. Настройка эскалации блокировки для таблицы отключена ... Я пробовал и другие доступные настройки таблицы и AUTO без каких-либо изменений. Я пробовал SELECT ... WITH (NOLOCK) и немедленно возвращает результат, но как хорошо предупрежден here и в других местах это не то, что я должен делать. Я попытался поставить подсказку ROWLOCK как на INSERT и UPDATE, но ничего не изменилось.

Поведение, которое я ищу, это следующее: до совершения INSERT, запросы из других потоков читают все строки, кроме один из которых является INSERT ed. Перед фиксацией запросов UPDATE из других потоков прочитайте стартовую версию строки UPDATE ред. Есть ли способ сделать это? Если мне нужно предоставить другую информацию, чтобы уточнить мой вариант использования, пожалуйста, дайте мне знать. Спасибо.

11 голосов | спросил John Riehl 24 Jpm1000000pmSun, 24 Jan 2016 22:34:29 +030016 2016, 22:34:29

2 ответа


7

Скорее всего, он не блокирует «целую таблицу».

Это блокировка строки в таблице, но ваш SELECT * FROM LAYOUTSv2 пытается прочитать всю таблицу, поэтому обязательно блокируется этой блокировкой.

Для случая вставки вы можете просто указать подсказку READPAST, чтобы пропустить мимо заблокированной строки, однако это не даст желаемого результата для случая UPDATE (он снова пропустит строку, не прочитав стартовую версию строки).

Если вы сконфигурируете базу данных для прочитайте выделенную блокировку моментальных снимков даст вам желаемый эффект для обоих случаев (за счет большего использования tempdb)

ответил Martin Smith 24 Jpm1000000pmSun, 24 Jan 2016 22:41:59 +030016 2016, 22:41:59
2

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

https://technet.microsoft. ком /EN-US /библиотека /ms184286 (v = sql.105) .aspx

ответил Suraj 28 WedEurope/Moscow2016-12-28T00:56:59+03:00Europe/Moscow12bEurope/MoscowWed, 28 Dec 2016 00:56:59 +0300 2016, 00:56:59

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132