Страницы

Поиск по вопросам

понедельник, 6 января 2020 г.

Блокировка только одной строки

#sql #oracle


Какие строки заблокируются в запросе

select m.id, m.is_ready from machine m join estar e on m.id = e.machine_id where
e.status = 'COMP' FOR UPDATE


Интересует блокируется ли строка из таблицы estar и если все таки блокируется как
сделать чтобы блокировала только строка из таблицы machine.
    


Ответы

Ответ 1



Для блокировки только записей в одной таблице (или нескольких на выбор, но не всех) можно воспользоваться: select ... for update of tab1.colnam, tab2.colnam. Так будует осуществлена строчная блокировка только таблиц - tab1 и tab2. Какую колонку из существующих в таблице указывать, не играет абсолютно никакого значения. Т.к. субзапрос выполняется отдельно от основного, строчки таблиц указанных в нём не будут заблокированы. И наоборот, если субзапрос содержит - for update, а основной нет, строчки из таблиц основного запроса не будут заблокированны. Пременимо к запросу из вопроса: select m.id, m.is_ready from machine m join estar e e.machine_id = on m.id where e.status = 'COMP' FOR UPDATE of m.is_ready ; Наглядный пример использующий схему SH: select cu.cust_id, cu.cust_last_name, co.country_name from customers cu join countries co on co.country_id=cu.country_id where cu.cust_id = 69 for update ; select o.object_name, o.object_type, s.sid, s.serial#, s.status from v$locked_object l join v$session s on s.sid = l.session_id join dba_objects o on o.object_id = l.object_id ; OBJECT_NAM OBJECT_TYP SID SERIAL# STATUS ---------- ---------- ------ ------- ---------- CUSTOMERS TABLE 22 19511 ACTIVE COUNTRIES TABLE 22 19511 ACTIVE 2 rows selected. SQL> rollback; Rollback complete. select cu.cust_id, cu.cust_last_name, co.country_name from customers cu join countries co on co.country_id=cu.country_id where cu.cust_id = 69 for update of cu.cust_income_level ; --*** повторяem выборку текущих блокировок *** OBJECT_NAM OBJECT_TYP SID SERIAL# STATUS ---------- ---------- ------ ------- ---------- CUSTOMERS TABLE 22 19511 ACTIVE 1 row selected.

Ответ 2



Насколько я понимаю суть работы FOR UPDATE, он должен заблокировать все строки, которые считываются в запросе. И неважно - входят ли столбцы из них в набор, который видит конечный пользователь. Если в Вашем случае строка в таблице estar, связанная со строкой в machine не будет заблокирована, то она может быть изменена до завершения транзакции. А это приведёт к тому что выборка данных станет неактуальна. Не вижу смысла в такой блокировке. Хотя надёжнее всего в Вашем случае проверить как именно реализована работа FOR UPDATE в Oracle. Заполните таблицу тестовыми данными, такими чтобы точно знать, что должно заблокироваться. Сделайте свой запрос с SELECT FOR UPDATE, но COMMIT не делайте. Затем начните параллельно ещё одну транзакцию. В ней попытайтесь обновить строку, которая по Вашим подсчётам должна быть заблокирована. Если вторая транзакция будет ждать, пока в первой COMMIT не сделаете - значит я прав и блокировка на estar есть. P.S. Сделал бы эту проверку сам, но Oracle под рукой нет)

Комментариев нет:

Отправить комментарий