Дуже багато новачка в роботі з БД, тому оцініть терпіння з основним питанням. Я запускаю 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)
і це негайно повертає результат, але як це добре застережено тут і в інших місцях, це не те, що я повинен робити. Я спробував поставити ROWLOCK
підказку і на, INSERT
і на UPDATE
твердження, але нічого не змінилося.
Поведінка, яку я шукаю, така: перед введенням INSERT
запиту з інших потоків читаються всі рядки, крім тієї, що INSERT
редагується. Перед тим, як здійснити UPDATE
запит з інших потоків, прочитайте початкову версію рядка, що UPDATE
редагується. Чи я можу це зробити? Якщо мені потрібно надати іншу інформацію для роз'яснення мого випадку використання, будь ласка, дайте мені знати. Спасибі.
newkey
значення " something';DELETE FROM LAYOUTSv2 --
". Ваше оновлення буде завершено успішно, а потім випорожнить таблицю, оскільки користувач маніпулював запитом, вставивши апостроф. Зазвичай параметризований запит виглядає приблизно так UDPATE LAYOUTSv2 SET LAYOUTS_enabled_b='-3' WHERE LAYOUTS_key=?
, після чого ви окремо присвоюєте значення (значення) ?
(параметру) у своєму коді.
WHERE LAYOUTS_key='" + newkey + "'
, це повне "ні-ні" з різних причин, включаючи введення SQL, ви повинні використовувати параметризовані запити.