Чи призведе до збільшення затримки мережі через блокування таблиць у MS SQL Server?


16

Якщо я здійснюю один виклик до бази даних SQL Server через мережу з високою затримкою, чи відбуватимуться блокування таблиці через цю затримку? Скажіть, я запитую таблицю A для деяких записів, і SQL Server повинен повернути ці дані через повільну мережу - чи буде блокування читання в таблиці A, поки сервер надсилає відповідь по мережі, або SQL Server звільняє блокування перед відправкою відповідь?

Також, чи буде відповідь змінюватися залежно від розміру відповіді? Якщо для цього потрібно лише повернути кілька Кб проти кількох сотень МБ, чи не зміниться це?

Створення явної транзакції, виконання запитів та закриття транзакції очевидно призведе до блокування таблиць, оскільки тривалість транзакції співвідноситься з моєю затримкою.


Якщо ви не вкажете nolockпідказку, замок завжди буде . Затримка просто визначає, як довго буде триматися замок.
Брендон


@brandon Це документує Microsoft де-небудь? Мої пошуки виявилися порожніми.
Еван М

1
@Brandon NOLOCK не означає, що ти думаєш, що це означає.
Аарон Бертран

3
@Brandon Unless you specify a nolock hint, there will always be a lock.<- це означає, що якщо ви користуєтесь нолоком, можливо не буде замків. Я просто уточнював.
Аарон Бертран

Відповіді:


15

Якщо клієнтові потрібно тривалий час для отримання даних і, в свою чергу, надсилає підтвердження SQL Server, що він отримав дані, яким SQL Server повинен чекати, через це очікування SQL Server не випустить блоки, що зберігаються в запиті, якщо підтвердження не буде отримано від клієнта.

Це не точно, це залежить від рівня ізоляції.

За замовчуванням READ COMMITTEDблокування не проводиться протягом тривалості виконання операторів. READ COMMITTEDне забезпечує узгодженість зчитування на рівні висловлювань, єдиною гарантією є те, що ви не можете читати непередані дані. Спільний замок набувається і утримується для читання рядка, а потім відпускається.

Якщо у вас немає типів LOB.

Типи LOB, будучи потенційно дуже великими, не можуть бути буферними. Спільний замок потрібно придбати та утримувати до завершення заяви, що по суті дає вам REPEATABLE READповедінку на READ COMMITTED.

Якщо я здійснюю один виклик до бази даних MSSQL через мережу з високою затримкою, чи відбуватимуться блокування таблиці через цю затримку?

Затримка не викликає блокування таблиці, ні. Однак, якщо замок столу був придбаний, затримка його продовжить.

Цитувати когось, хто знає механіку цього краще, ніж я ( @RemusRusanu ):

Результати повертаються назад до клієнтської програми в міру тривання виконання. Коли рядки "бульбашки" складаються з дерева виконання, верхній оператор, як правило, має завдання записувати ці рядки в мережеві буфери та відправляти їх назад клієнту. Результат створюється не спочатку в деякому проміжному сховищі (пам'яті або диску), а потім надсилається назад клієнту, а натомість він надсилається назад, як створюється (як виконується запит). Передача результату клієнту, звичайно, підпорядковується протоколу управління мережевим потоком. Якщо клієнт не активно споживає результат (наприклад, зателефонувавши на SqlDataReader.Read ()), з часом контроль потоку повинен буде заблокувати сторону відправки (запит, який виконується), а це, в свою чергу, призупинить виконання запит.[джерело]

Якщо результати не споживаються так швидко, як SQL Server може їх доставити, будь то завдяки клієнту чи мережі, ми бачимо, що ASYNC_NETWORK_IOнакопичення чекає. Знову повторюю, це не вплине на придбані замки, просто на тривалість їх проведення.


9

Відповідь Марка очистила багато моєї плутанини, але я хотів опублікувати свої висновки після того, як я перевірив це за допомогою NetBalancer для імітації затримок.

Я змусив свою локальну машину зателефонувати на віддалений сервер SQL і виконати SELECT і INSERT на столі в рамках невеликої транзакції. На віддаленій машині я підключився до локального екземпляра SQL і використав цикл WHILE, щоб неодноразово повторювати таблицю sys.dm_tran_locks, шукаючи будь-які блоки в таблиці, з якої я змінював та читав. Я встановив NetBalancer на сервер і використовував його для імітації затримки мережі на мережевому з'єднанні сервера.

Ось що я знайшов:

  • Для тверджень, які не повертають багато даних клієнту, затримка не впливає на блокування. Я повертав лише декілька сотень байт даних. Транзакція на моїй машині мала 250-футневий WAITFOR, який зберігав замки, і коли я наробив затримку в мережі до 5000 мс, тривалість блокування залишилася близько 250 мс.
  • Для тверджень, які повертають багато даних, затримка, безумовно, впливає на блокування, я повернув десятки тисяч рядків назад клієнту, і без затримки тривалість блокування була короткою. Коли я збільшив затримку, блокування тривало, поки я не отримав усі дані.

З цього я роблю висновок, що затримка не має значення, поки дані вміщуються в мережевий буфер. Якщо SQL повинен помістити багато даних у мережевий буфер, затримка призведе до того, що цей буфер резервується, і SQL буде тримати блоки таблиці, поки він не зможе поставити всі результати запиту в буфер.


Цікаві результати. З якою програмою / бібліотекою клієнтів це?
Джеймс Л

Хороший матеріал. Будь-який шанс ви можете витратити на це трохи більше часу і побачити, чи можете ви визначити розмір результату, при якому це відбувається?
Марк Сторі-Сміт

@ MarkStorey-Smith Я не думаю, що я можу отримати точне значення, і це, безсумнівно, буде залежати від машини. З vircom.com/security/improve-sql-nic-performance , схоже, це налаштування для вашого локального NIC, а для мого сервера баз даних було встановлено значення "auto"
Evan M

@James Я щойно використовував SSMS на обох машинах
Evan M

0

Якщо я здійснюю один виклик до бази даних MSSQL через мережу з високою затримкою, чи відбуватимуться блокування таблиці через цю затримку?

Коли запит запущений і виконаний SQL Server, він видає результати, помістіть його у вихідний буфер і надішліть його клієнту, який потім отримує результат з вихідного буфера. SQL Server не буде випускати блоки, які зберігаються в запиті, якщо не буде отримано підтвердження від клієнта. Що може призвести до блокування.

Редагувати: Еван, ви можете звернутися до цієї статті підтримки MS

У розділі 3

Блокування, спричинене SPID, чия відповідна клієнтська програма не отримала всі ряди результатів до завершення

Після відправлення запиту на сервер усі програми повинні негайно отримати всі рядки результатів до завершення. Якщо програма не отримує всіх результативних рядків, блоки можна залишити на таблицях, блокуючи інших користувачів. Якщо ви використовуєте програму, яка прозоро подає оператори SQL на сервер, програма повинна отримати всі результати рядків. Якщо цього немає (і якщо його не вдається налаштувати), можливо, ви не зможете вирішити проблему блокування. Щоб уникнути проблеми, ви можете обмежити недоброзичливі програми до звітів або бази даних підтримки прийняття рішень.


Дякую за вашу відповідь, Шанкі! Чи знаєте ви, чи це документується десь?
Еван М


5
Це неправильно.
Марк Сторі-Сміт

Це правильно, здається, що програма не отримує всі результати рядків, блокування можна залишати на таблицях, блокуючи інших користувачів. Якщо ви використовуєте програму, яка прозоро подає оператори SQL на сервер, програма повинна отримати всі результати рядків. Якщо цього немає (і якщо його не вдається налаштувати), можливо, ви не зможете вирішити проблему блокування. Щоб уникнути проблеми, ви можете обмежити недоброзичливі програми до звітів або бази даних підтримки рішення. " Більше я говорив у загальних рисах. Ви можете прочитати тут support2.microsoft.com/kb/224453
Shanky

4
@Shanky Створіть велику таблицю. SELECT *від нього в at READ COMMITTEDв одному підключенні SSMS, блокування монітора з іншого. У будь-який час, скільки замок ви вважаєте, що вони утримуються?
Марк Сторі-Сміт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.