Очень новичок в работе с БД, поэтому оцените ваше терпение по основному вопросу. Я использую 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, назначенное в качестве первичного ключа. В окне свойств он показывает, что он уникален и кластеризован, с блокировками страниц и строк. Параметр повышения блокировки для таблицы: «Отключить». Я пробовал оба других доступных параметра «Таблица» и «АВТО» без изменений. Я пытался, SELECT ... WITH (NOLOCK)
и это немедленно возвращает результат, но, как хорошо здесь и в других местах, это не то, что я должен делать. Я попытался положить ROWLOCK
намек на обоих INSERT
и UPDATE
заявления, но ничего не изменилось.
Я ищу следующее: перед фиксацией an INSERT
запросы из других потоков читают все строки, кроме той, которая INSERT
редактируется. Перед принятием UPDATE
запросов из других потоков прочитайте начальную версию редактируемой строки UPDATE
. Есть ли способ, которым я могу сделать это? Если мне нужно предоставить другую информацию для уточнения моего варианта использования, пожалуйста, дайте мне знать. Благодарю.
источник
WHERE LAYOUTS_key='" + newkey + "'
по разным причинам, включая внедрение SQL-кода, полное нет-нет, следует использовать параметризованные запросы.newkey
на "something';DELETE FROM LAYOUTSv2 --
". Ваше обновление будет успешно завершено, а затем таблица будет очищена, поскольку пользователь манипулирует запросом, вставляя апостроф. Обычно параметризованный запрос выглядит примерно такUDPATE LAYOUTSv2 SET LAYOUTS_enabled_b='-3' WHERE LAYOUTS_key=?
, после чего вы отдельно присваиваете значение (?
параметры) в своем коде.Ответы:
Скорее всего, это не блокирует "весь стол".
Он блокирует строку в таблице, но вы
SELECT * FROM LAYOUTSv2
пытаетесь прочитать всю таблицу, поэтому эта блокировка обязательно блокируется.Для случая вставки вы можете просто указать
READPAST
подсказку, чтобы пропустить заблокированную строку - однако это не даст желаемого результата дляUPDATE
случая (оно снова пропустит строку, не прочитав начальную версию строки).Если вы сконфигурируете базу данных для изоляции зафиксированных моментальных снимков, это даст желаемый эффект в обоих случаях (за счет более широкого использования
tempdb
)источник
SNAPSHOT
изоляцию, лучше всего оставить ее отключенной, а затем включить ее, если впоследствии вы решите, что это будет полезно для вас.Операторы вставки и обновления должны создавать блокировки на уровне строк. Однако, когда количество блокировок в любой транзакции составляет 5000 или более, происходит эскалация блокировки, и она создает блокировку на уровне таблицы. Пожалуйста, смотрите ниже.
https://technet.microsoft.com/en-us/library/ms184286(v=sql.105).aspx
источник