Проблема эскалации блокировки SQL Server
Я читаю повышение блокировки SQL Server со страницы MSDN о повышении блокировки SQL Server
Мой вопрос заключается в том, что основная причина, по которой происходит эскалация блокировок, заключается в уменьшении накладных расходов для поддержания большего количества блокировок (например, когда для таблицы получено больше блокировок строк, блокировка на уровне строк повышается до уровня таблиц). Мой вопрос заключается в том, что поддержание большего количества блокировок улучшит параллелизм, это преимущество, почему это накладные расходы? По моей скромной идее, блокировка должна быть настолько малой, чтобы повысить производительность БД за счет улучшения параллелизма. Может ли кто-нибудь объяснить простым способом, почему требуется эскалация блокировки и каковы так называемые издержки блокировки, пожалуйста?
спасибо заранее, Джордж
5 ответов
Может ли кто-нибудь объяснить простым способом, почему требуется эскалация блокировки и каковы так называемые издержки блокировки, пожалуйста?
Когда вы обновляете таблицу и блокируете строку, вам нужно как-то записать этот факт: это строка, она была обновлена и заблокирована.
Когда вы обновляете миллион строк, вам нужно делать это миллион раз, и, следовательно, есть место для хранения миллионов блокировок.
SQL Server хранит список блокировок в памяти, а Oracle - в табличных пространствах.
Вероятно, это связано с тем, что Oracle старше (старше меня), а SQL Server более молодой по сравнению с Oracle.
Хранение временных ресурсов (таких как блокировки) в постоянном хранилище не является очевидным решением с точки зрения дизайнера. Стоит упомянуть одну вещь: вам может понадобиться запись на диск для выполнения SELECT FOR UPDATE
,
Основные функции Oracle были разработаны в начале 80-х годов, когда хранение вещей в памяти вообще не было возможным. Им просто нужно было как-то использовать дисковое пространство.
Если дисковое пространство должно было быть использовано в любом случае, вы должны были установить блокировку где-нибудь на диске.
И где хранить блокировку для строки, если не в самой строке?
Разработчики системы блокировки SQL Server, придумывая дизайн своей СУБД под названием Sybase, решили хранить временные объекты (например, блокировки) во временном хранилище (например, в ОЗУ).
Но дизайн Oracle всегда сбалансирован: если у вас есть 1000 000 строк в вашей базе данных, то у вас есть место для хранения 1000 000 блокировок, если у вас есть миллиард строк, вы можете хранить миллиард блокировок и т. Д.
Конструкция SQL Server в этом смысле несовершенна, поскольку пространство в оперативной памяти и на жестком диске может быть несбалансированным. Вы можете легко иметь 16M RAM и несколько терабайт дискового пространства. И ваша память просто не может удержать все замки.
Вот почему, когда количество блокировок достигает определенного предела, SQL Server принимает решение об усилении блокировок: вместо сохранения, скажем, 10 отдельных строк на странице данных (для чего требуется 10 записей), он блокирует всю страницу данных (для чего требуется 1 запись).
Oracle, с другой стороны, при обновлении строки просто записывает блокировку прямо в страницу данных.
Вот почему блокировки Oracle на уровне строк.
Oracle не "управляет" блокировками в обычном смысле слова: вы не можете, скажем, получить список заблокированных страниц в Oracle.
Когда транзакция должна обновить строку, она просто переходит к строке и видит, заблокирована ли она.
Если это так, он смотрит, какая транзакция удерживает блокировку (эта информация содержится в дескрипторе блокировки на странице данных), и добавляет себя в очередь уведомлений этой транзакции: когда блокирующие транзакции умирают, исходная получает уведомление и блокирует данные.
С точки зрения параллелизма, эскалация блокировок - это решение бедняков: оно ничего не добавляет к параллелизму. Вы можете, скажем, получить блокировку на ряду, который вы даже не трогали.
С точки зрения производительности, делать что-то в памяти, конечно, быстрее, чем делать это на диске.
Но поскольку Oracle кеширует блоки данных, и фактические операции, описанные выше, в любом случае выполняются в памяти, производительность остается такой же или близкой к ней.
Если оптимизатор SQL Server оценивает / решает, что запрос "посетит" все строки в определенном диапазоне, будет эффективнее удерживать одну блокировку в этом диапазоне, а не согласовывать много блокировок (блокировки должны быть проверены на тип). Это в дополнение к потреблению меньшего количества ресурсов блокировки (общесистемного ресурса).
Если у вас хорошо продуманная схема и индексы, соответствующие вашей рабочей нагрузке, которые регулярно поддерживаются, вам не нужно беспокоиться о происходящей эскалации. Во многих случаях блокирующие блокировки таблиц могут быть устранены соответствующими индексами покрытия.
ОБНОВЛЕНИЕ: закрывающий индекс для запроса означает, что поиск в кластере выполнять не нужно, и это снижает шансы на блокировку вставок в таблицу.
Определение "эффективный" является сложным. Иногда более эффективно оптимизировать параллелизм, если множество процессов могут делать это без коллизий. Иногда эффективнее использовать временное совпадение, чтобы ускорить выполнение одного процесса. Ускоренная блокировка будет препятствовать другим процессам, чтобы ЭТОТ процесс мог выполнить свою работу и уйти с дороги.
Для получения конкретной информации о том, как поддерживаются блокировки, вы можете увидеть главу 8 Microsoft SQL Server 2005: Механизм хранения (я не связан, это только первая внутренняя информация, с которой я столкнулся). Если у вас есть аккаунт books24x7, он там есть. Он показывает, что на машине с памятью>16 ГБ в хэш-таблице блокировки есть 2^25 (33554432) слотов с верхним пределом 2^31 слотов.
Для данного приложения вы можете найти общую пропускную способность выше, используя только мелкозернистые блокировки. Как вы, вероятно, можете догадаться, все зависит от того, насколько издержки управления блокировками сравниваются с потенциальной чрезмерной блокировкой.
Издержки блокировки означают, что управление одной блокировкой таблицы лучше, чем управление множеством блокировок строк. так как каждая блокировка требует некоторой памяти, много блокировок строки могут потреблять намного больше памяти, чем одна блокировка таблицы. Таким образом, повышение блокировки происходит от строки-> страницы-> блокировки таблицы.