Форум программистов, компьютерный форум, киберфорум
C#: Базы данных
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/4: Рейтинг темы: голосов - 4, средняя оценка - 4.75
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,768

Блокировка при чтении?

20.07.2022, 09:14. Показов 989. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть типовой пример взаимной блокировки ресурса.
T-SQL
1
2
3
4
5
create table smp
(
    smp_id int not null identity(1, 1) primary key,
    some_data varchar(84) not null,
);
T-SQL
1
2
3
4
5
6
7
8
9
10
set transaction isolation level serializable;
begin transaction;
 
select * from smp /*with (tablockx)*/ where smp.some_data = '1234';
 
-- какая-то БЛ, анализ результатов 'select', принятие решения на модификацию/добавление
 
insert into smp (some_data) values ('1234');
 
commit transaction;
1. Первое подключение выполняет 'select', второе подключение тоже выполняет 'select' (который не блокируется, т.к. select накладывает на ресурс блокировку 'shared lock', которая не блокирует чтение).
2. Оба подключения, проанализировав результаты запроса, принимают решение добавить запись в БД.
3. Первый 'insert' упирается в блокировку от второго 'select', второй 'insert' - в блокировку от первого 'select'.
4. Ок, deadlock, sqlserver немного подождёт, сгенерирует соответствующую ошибку для одного из коннектов, закроет его транзакцию, а другой коннект при этом завершится корректно. Данные согласованы, но реализация через deadlock и отлов соответствующего исключения выглядит слишком костыльно.

Вопрос - как это правильно решать без переноса части БЛ в базу и без взаимных блокировок?

Если снизить уровень изоляции, то взаимной блокировки не будет, но и согласованность данных тогда не гарантируется, т.к. 'insert' будет происходить не в том состояние таблицы, в котором она была на момент 'select'.

Блокировать на уровне логики приложения - весьма сложная задача (экземпляров сервера может быть много, база общая).

Вариант, который работает - выборка с эксклюзивной блокировкой таблицы (закомментированный фрагмент 'with (tablockx)'). Но подобное решение вызывает некоторые сомнения, т.к. и упоминается (хотя сценарий вполне типовой) мало где, и в EFCore для этого дефолтного функционала нет.

Вероятно, это можно решить как-то иначе?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
20.07.2022, 09:14
Ответы с готовыми решениями:

Блокировка файла при чтении и записи
осуществляется работа с одним и тем же файлом. Каждый процесс открывает файлОдин процесс пишет в файл, другой - читает из него. нужно...

"Нарушение прав доступа при чтении по адресу" при чтении структур из бинарного файла
Пытаюсь разобраться со структурами в бинарных файлах. Допустим, есть массив структур. Записываю его в бинарный файл (закомментированный...

Блокировка клавиши при нажатии в одной форме и блокировка в другой, третьей
Здравствуйте нужно что бы при вызове помощи в 1ом вопросе она блокировалась во 2ом вопросе,подскажите как сделать. Вам нужно...

6
Эксперт .NET
 Аватар для Usaga
14314 / 9399 / 1355
Регистрация: 21.01.2016
Сообщений: 35,447
20.07.2022, 13:15
Цитата Сообщение от kotelok Посмотреть сообщение
Вариант, который работает - выборка с эксклюзивной блокировкой таблицы (закомментированный фрагмент 'with (tablockx)').
Максимально фиговый вариант в большинстве случаев. Гасит конкуретный доступ к данным на корню.

Цитата Сообщение от kotelok Посмотреть сообщение
но реализация через deadlock и отлов соответствующего исключения выглядит слишком костыльно.
Разве?
1
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,768
20.07.2022, 13:55  [ТС]
Цитата Сообщение от Usaga Посмотреть сообщение
Максимально фиговый вариант в большинстве случаев. Гасит конкуретный доступ к данным на корню.
Да, уже заметил, особенно в ситуации, когда количество операций чтения, превосходит количество операций обновления на несколько порядков и требуется максимально быстрое конкурентное чтение.
Цитата Сообщение от Usaga Посмотреть сообщение
Разве?
На первый взгляд да. Но это, похоже, самый оптимальный вариант - при отлове специфичного deadlock-исключения либо выдать HTTP-500, либо просто тихо повторить попытку (сколько-то раз) и почти наверняка получить успешное завершение.
0
 Аватар для Andrey-MSK
3360 / 2246 / 388
Регистрация: 14.08.2018
Сообщений: 7,589
Записей в блоге: 4
20.07.2022, 14:01
kotelok, А какой шанс того, что одни и те же данные будут редактировать два пользователя одновременно?
Может проще использовать timestamp и при сохранении данных проверять его? Если разные, то вывести пользователю новые данные для сравнения...
1
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,768
20.07.2022, 14:17  [ТС]
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
А какой шанс того, что одни и те же данные будут редактировать два пользователя одновременно?
Не обязательно одни и те же. Выше сценарий с добавлением записи в таблицу с предварительным сканированием. Там, при serializable-транзакции, select накладывает на таблицу блокировку, которая, пока транзакция не закрыта, блокирует добавление записей в эту таблицу из других транзакций. На одном из приложений именно этот сценарий изредка повторяется, когда сразу десяток пользователей одновременно запускают процесс массовой обработки данных

И не обязательно два разных пользователя. Сейчас, на другом проекте, этот сценарий стабильно повторяется в рамках одного пользователя в силу особенностей реализации клиентской части. Пользователь нажимает "ок", клиентское приложение создаёт два таска на обращение к API и далее параллельно их выполняет. В итоге, в режиме отладки и при localhost-сервере, эти запросы приходят на сервер достаточно одновременно, чтобы наступить на эту взаимную блокировку.

Добавлено через 1 минуту
Цитата Сообщение от Andrey-MSK Посмотреть сообщение
Может проще использовать timestamp и при сохранении данных проверять его? Если разные, то вывести пользователю новые данные для сравнения...
Это другой сценарий. Т.е. при сценарии:
1. Взяли сущность из БД.
2. Модифицировали.
3. Сохраняем обратно.

Действительно удобен какой-то вариант 'row version' (timestamp, например). И он корректно работает даже если три обозначенных выше пункта сильно разнесены во времени и выполняются в рамках разных транзакций.
0
Эксперт .NET
 Аватар для Usaga
14314 / 9399 / 1355
Регистрация: 21.01.2016
Сообщений: 35,447
20.07.2022, 16:10
Цитата Сообщение от kotelok Посмотреть сообщение
Это другой сценарий. Т.е. при сценарии:
1. Взяли сущность из БД.
2. Модифицировали.
3. Сохраняем обратно.
Это почти чистой воды сценарий работы EF'а) Это значит, что это хорошо)

Цитата Сообщение от kotelok Посмотреть сообщение
Действительно удобен какой-то вариант 'row version' (timestamp, например). И он корректно работает даже если три обозначенных выше пункта сильно разнесены во времени и выполняются в рамках разных транзакций.
Он мало чем отличается от deadlock. Вот вы выдали UPDATE ... WHERE ID=.. AND ROWVERSION=.., вот вы получили нуль затронутых версий. Опять надо UPDATE выдавать.

Добавлено через 4 минуты
Вариант с оптимистичными блокировками самый оптимальный, на самом деле. На втором месте по адекватности идёт уже SELECT ... FOR\WITH UPDATE. Тут уже другие транзакции с таким же типом лока будут вставать в очередь. Если не злоупотреблять, то вполне себе вариант. Уж точно лучше, чем полная блокировка всей таблицы...

Ну и то, что такие вещи не доступны пользователям EF'а... Проблемы этих пользователей...
1
 Аватар для Cupko
658 / 595 / 171
Регистрация: 17.07.2012
Сообщений: 1,682
Записей в блоге: 1
23.07.2022, 14:00
Цитата Сообщение от kotelok Посмотреть сообщение
Если снизить уровень изоляции, то взаимной блокировки не будет, но и согласованность данных тогда не гарантируется, т.к. 'insert' будет происходить не в том состояние таблицы, в котором она была на момент 'select'.
Что у вас за задача такая, что нужно таблицу лочить целиком?

Если MSSQL - можно юзать SNAPSHOT уровни.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
23.07.2022, 14:00
Помогаю со студенческими работами здесь

Нарушение прав доступа при чтении при работе с большим массивом
Здравствуйте. Пытаюсь заполнить большой массив, вроде правильно объявил его, но на разных итерациях (от i=92106 и выше ...) появляется...

Ошибка при чтении символов строки при создании объекта класса
У меня имеется класс Song, в котором присутствуют поля имени песни (Name) и длительности песни (Duration). Также в этом классе есть...

Ошибка при добавлении элементов в список при чтении файла
Есть файл с информацией о всех профилях, который читается reader-ом. Записи в нем выглядят вот так: ID: 1 Name: xxx Mode1_Slozhn: ...

Ошибка при вызове метода класса, при чтении из файла
добрый день, пытаюсь считать данные из и запихнуть их в список в файле у меня вот такие данные a01 b10 А и Б надо запихнуть в...

Абракадабра при записи в файл и при чтении из него кириллицы
#include <iostream> #include <fstream> using namespace std; int main() { ofstream f("text.dat"); f << "Тест"; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
модель ЗдравоСохранения 8. Подготовка к разному выполнению заданий
anaschu 08.04.2026
https:/ / github. com/ shumilovas/ med2. git main ветка * содержимое блока дэлэй из старой модели теперь внутри зайца новой модели 8ATzM_2aurI
Блокировка документа от изменений, если он открыт у другого пользователя
Maks 08.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в конфигурации КА2. Задача: запретить редактирование документа, если он открыт у другого пользователя. / / . . .
Система безопасности+живучести для сервера-слоя интернета (сети). Двойная привязка.
Hrethgir 08.04.2026
Далее были размышления о системе безопасности. Сообщения с наклонным текстом - мои. А как нам будет можно проверить, что ссылка наша, а не подделана хулиганами, которая выбросит на другую ветку и. . .
Модель ЗдрввоСохранения 7: больше работников, больше ресурсов.
anaschu 08.04.2026
работников и заданий может быть сколько угодно, но настроено всё так, что используется пока что только 20% kYBz3eJf3jQ
Дальние перспективы сервера - слоя сети с космологическим дизайном интефейса карты и логики.
Hrethgir 07.04.2026
Дальнейшее ближайшее планирование вывело к размышлениям над дальними перспективами. И вот тут может быть даже будут нужны оценки специалистов, так как в дальних перспективах всё может очень сильно. . .
Горе от ума
kumehtar 07.04.2026
Эта мне ментальная установка, что вот прямо сейчас, мол, мне для полного счастья не хватает (нужное вписать), и когда я этого достигну - тогда и полный кайф. Одна из самых сильных ловушек на пути. . . .
Использование значений реквизитов справочника в документе, с определенными условиями и правами
Maks 07.04.2026
1. Контроль срока действия договора Алгоритм из решения ниже реализован на примере нетипового документа "ЗаявкаНаРаботу", разработанного в конфигурации КА2. Задача: уведомлять пользователя, если. . .
Доступность команды формы по условию
Maks 07.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: сделать доступной кнопку (команда формы "ЗавершитьСписание") при. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru