Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Microsoft SQL Server |
![]() ![]() |
no56892 Member Откуда: Сообщений: 590 |
Никак не могу понять как в скл сервере работают блокировки. Допустим есть таблица T с 3 полями INT A, B, C. Без индексов. И там 4 записи, у двух например в поле А значение 1. Уровень транзакций - READ COMMITTED. Что происходит при выполнении запроса: UPDATE T set B = 1 WHERE A = 1 ? Допустим каждая запись это ROW. Начинается TABLE SCAN. 1.Попытка установить блокировку U на ROW1. Если успешно идем дальше, нет - ждем. 2.Аналогично для ROW2 3.Аналогично для ROW3 4.Аналогично для ROW4 То есть в какой то момент на всех записях стоит U? Либо на каждом шаге проверяется условие и только тогда ставится U? В какой момент она заменятся на Х? перед самым коммитом? Собственно если параллельно выполнить запрос SELECT * FROM T WHERE C = 10 То при условии что записи будут блокироваться в разном порядке возможен дедлок? Селект наткнулся на ROW на котором апдейт уже оставил U, в то же время апдейт не сможет сделать из U->X тк на записи стоит S от селекта? |
8 ноя 19, 21:58 [22012617] Ответить | Цитировать Сообщить модератору |
invm Member Откуда: Москва Сообщений: 9646 |
В вашем конкретном случае сканирования кучи, упрощенно: - на строку ставится U - если строка удовлетворяет предикату, U конвертируется в X и значение столбца обновляется, иначе U снимается. И так для каждой сканируемой строки. |
||||
8 ноя 19, 22:31 [22012625] Ответить | Цитировать Сообщить модератору |
Gerros Member Откуда: Харьков Сообщений: 508 |
Если select в serializable, а update по-прежнему в read committed, deadlock тоже не случается: select не снимает наложенный S-lock до завершения транзакции, но update снимает X-lock после каждого изменения. Что бы ни делал update, select рано или поздно прочитает всё что ему нужно и снимет свой S-lock, после чего update сможет продолжить и завершить свою работу. Deadlock-и возникают, когда оба конкурирующих процесса в repeatable read и выше. |
||||
9 ноя 19, 01:16 [22012647] Ответить | Цитировать Сообщить модератору |
felix_ff Member Откуда: Moscow Сообщений: 1698 |
no56892, добавлю к ответившим: что бы лучше понять механизм блокировок запустите на тестовых вариациях запросов трассироку/xevent на события lock:aquired/lock:released. тогда вы будете видеть наглядную картину что происходит в момент наложения/снятия блокировок |
9 ноя 19, 03:35 [22012654] Ответить | Цитировать Сообщить модератору |
invm Member Откуда: Москва Сообщений: 9646 |
no56892, Дополню. Дедлочность select- update (в смысле читатель - писатель) зависит от множества факторов: наличия индексов, TIL читателя, хинтов в запросе, порядка просмотра записей. Утверждение
Дедлочить может и когда читатель на read committed. Для писателя же TIL практически не важен. В вашем конкретном случае (таблица-куча без индексов) дедлока не будет, потому что читатель не накладывает более одной блокировки при обработке строки и не удерживает ее до конца транзакции. Изучать процессы блокирования с помощью Extended Events, ИМХО, слишком накладно. Гораздо проще в SSMS вот так (само-собой в тестовом окружении): use tempdb; go create table dbo.t (id int, a int); insert into dbo.t values (1, 0), (1, 2), (2, 3); create index IX_t__id on dbo.t (id); go /*Какие ресурсы будут блокироваться*/ select object_id('dbo.t'); select %%lockres%%, * from dbo.t; select %%lockres%%, * from dbo.t with (index = IX_t__id); go print '------------------------------------------ Table Scan -------------------------------------------------------'; begin tran; dbcc traceon(3604, 1200, -1) with no_infomsgs; update t set a = 100 from dbo.t t with (index = 0) where id = 1 and a > 0; dbcc traceoff(3604, 1200, -1) with no_infomsgs; rollback; print '-------------------------------------------------------------------------------------------------------------'; print '------------------------------------------ Index Seek -------------------------------------------------------'; begin tran; dbcc traceon(3604, 1200, -1) with no_infomsgs;; update t set a = 100 from dbo.t t with (index = IX_t__id) where id = 1 and a > 0; dbcc traceoff(3604, 1200, -1) with no_infomsgs; rollback; print '-------------------------------------------------------------------------------------------------------------'; go drop table dbo.t; go Результаты будут на вкладке messages |
||||
9 ноя 19, 14:21 [22012752] Ответить | Цитировать Сообщить модератору |
Все форумы / Microsoft SQL Server | ![]() |