Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / PostgreSQL Новый топик    Ответить
Топик располагается на нескольких страницах: 1 2      [все]
 Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
else12
Member

Откуда:
Сообщений: 245
Программным путем нужно определять кем заблокирована запись в таблице, и, в случае необходимости, разблокировать ее. Как это можно сделать?
10 фев 14, 12:48    [15545626]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
else12
Member

Откуда:
Сообщений: 245
Я как-то не правильно задал вопрос или проблема не решаема?
10 фев 14, 16:41    [15547287]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
else12
Member

Откуда:
Сообщений: 245
На всякий случай - блокировка записи производится с помощью FOR UPDATE NOWAIT с клиентской части.
10 фев 14, 16:43    [15547307]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
Ёш
Member

Откуда:
Сообщений: 2892
else12, у postgres нет ограничения на количество заблокированных строк, это достигается благодаря тому что запись о блокировке строки хранится в самой строке. То есть чтобы получить информацию — кем заблокирована запись в таблице, нужно просмотреть все строки в таблице. Например если у Вас таблица 20 Гб — то что бы ответить на Ваш вопрос, нужно просматривать 20Гб каждый раз.

Можно сделать по другому, убивать все сессии (pg_terminate_backend) с блокировкой RowShareLock на нужной таблице.

PS: но вы явно делаете что-то не то.
10 фев 14, 17:11    [15547480]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
else12
Member

Откуда:
Сообщений: 245
Ёш
else12, у postgres нет ограничения на количество заблокированных строк, это достигается благодаря тому что запись о блокировке строки хранится в самой строке. То есть чтобы получить информацию — кем заблокирована запись в таблице, нужно просмотреть все строки в таблице. Например если у Вас таблица 20 Гб — то что бы ответить на Ваш вопрос, нужно просматривать 20Гб каждый раз.

Можно сделать по другому, убивать все сессии (pg_terminate_backend) с блокировкой RowShareLock на нужной таблице.

PS: но вы явно делаете что-то не то.

Да у меня задача простая: в случае, если два пользователя обращаются к одной записи таблицы, то первый может ее редактировать, а второй только смотреть. И периодически возникают вопросы: "А кто сейчас заблокировал запись?" Записей в таблице, естественно, много и пользователей хватает. Нужно оперативно узнавать кто держит запись, желательно даже, чтобы пользователь сам видел кто блокирует запись, к которой он хочет обратиться.
10 фев 14, 17:26    [15547555]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
SmeL_md
Member

Откуда:
Сообщений: 1065
9.26.8. Advisory Lock Functions
Может стоит это использовать и отказаться от UPDATE NOWAIT. Пользователи всё смогут видеть, все смогут редактировать так как Вы захотите, и не будут висеть пока строка не освободится.
10 фев 14, 17:52    [15547675]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
SmeL_md
Member

Откуда:
Сообщений: 1065
Через NOTIFY можно самому признаваться, что редактируешь
10 фев 14, 17:57    [15547700]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
qwwq
Member

Откуда:
Сообщений: 2894
Ёш
else12, у postgres нет ограничения на количество заблокированных строк, это достигается благодаря тому что запись о блокировке строки хранится в самой строке. То есть чтобы получить информацию — кем заблокирована запись в таблице, нужно просмотреть все строки в таблице. Например если у Вас таблица 20 Гб — то что бы ответить на Ваш вопрос, нужно просматривать 20Гб каждый раз.

Можно сделать по другому, убивать все сессии (pg_terminate_backend) с блокировкой RowShareLock на нужной таблице.

PS: но вы явно делаете что-то не то.
оффтоп

ЯННП
, т.е. пользователь уже обрашается к конкретной строке - и именно она и заблокирована. на кой ему просматривать ещё 20ГБстрок, "чтобы блаблаблабла" ?
10 фев 14, 18:22    [15547791]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
qwwq
Member

Откуда:
Сообщений: 2894
SmeL_md
9.26.8. Advisory Lock Functions
Может стоит это использовать и отказаться от UPDATE NOWAIT. Пользователи всё смогут видеть, все смогут редактировать так как Вы захотите, и не будут висеть пока строка не освободится.
адвайзори лок не отдаст вам автора
т.е. совсем

к тому же если начать пользоваться АЛ на всех табличках, да в которых кеи -длинное целое - непонятно, как различать лонг в одной табле от лонга в другой. т.е. это какой-то такой полуфабрикат, которым можно пользоваться для демонстрации возможности, но нельзя (без хитрого саморезного винта) - в широкой практике.
10 фев 14, 18:26    [15547805]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
SmeL_md
Member

Откуда:
Сообщений: 1065
qwwq
...если начать пользоваться АЛ на всех табличках, да в которых кеи -длинное целое - непонятно, как различать лонг в одной табле от лонга в другой...

pg_advisory_lock(key1 int, key2 int)
10 фев 14, 18:33    [15547831]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
qwwq
Member

Откуда:
Сообщений: 2894
SmeL_md
qwwq
...если начать пользоваться АЛ на всех табличках, да в которых кеи -длинное целое - непонятно, как различать лонг в одной табле от лонга в другой...

pg_advisory_lock(key1 int, key2 int)

засуньте сюда 1 инт - tableoid + 1 лонг - pk

я таки немного попрактиковал в этой области, ага
т.ч. не надо тукать в меня домыслами
10 фев 14, 18:35    [15547842]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
Hawkmoon
Member

Откуда:
Сообщений: 745
qwwq
SmeL_md
пропущено...

pg_advisory_lock(key1 int, key2 int)

засуньте сюда 1 инт - tableoid + 1 лонг - pk

я таки немного попрактиковал в этой области, ага
т.ч. не надо тукать в меня домыслами


Чисто для непрактиковавших, можно попросить изложить быстро промелькнувшие за 2 минуты мысли письменно?
10 фев 14, 19:39    [15548046]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
Sergei.Agalakov
Member

Откуда:
Сообщений: 575
У вас, похоже, долгая бизнес транзакция. Типичный пример: кто-то делает checkout на документе, редактирует его 20 минут или час, а потом делает checkin обновленного документа с новым номером версии. Вешать ее на внутренний механизм транзакций в базе нехорошо. Обычно добавляют пару колонок checkedout timestamp, checkedoutby varchar(64). Первый пользователь в своей первой транзакции просто заполняет checkedout и checkedoutby, и выполняет коммит. После чего всем видно кто забрал документ, и когда.
Разумеется, приложение не должно пытаться обновлять документ кусками, а только одной транзакцией при checkin. Опять же надо чистить статусы у документов, которые кто-то забрал, а потом уехал в отпуск, а другим тоже надо. Но это лучше, чем держать в базе открыту. транзакцию часами, а т и днями.
10 фев 14, 20:25    [15548213]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
йццй
Guest
Hawkmoon
qwwq
пропущено...

засуньте сюда 1 инт - tableoid + 1 лонг - pk

я таки немного попрактиковал в этой области, ага
т.ч. не надо тукать в меня домыслами


Чисто для непрактиковавших, можно попросить изложить быстро промелькнувшие за 2 минуты мысли письменно?
можно,

мысль простая:
в общем случае нам надо лочить объект, состоящий из ид таблицы, и ключа в ней. т.е. в идеале int4 + hstore (как вариант int + text[]. на худой - int + text)
нам предлагают лочить или bigint (only) или пару чисел (int,int)
уже для пары (int {tableoid},bigint {pkey}) этого недостаточно
если не пририсовывать тяжело груженых велосипедов, осуществляющих мапинг теущего набора залоченных бигинтов (ну не ярды же записей одновременно "залочены") [или ключей иного состава] на мн-во интов.

собственно выше всё это уже сказано. имеющий уши, но кто ж их моет, ага.
10 фев 14, 20:26    [15548220]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
Ёш
Member

Откуда:
Сообщений: 2892
qwwq
т.е. пользователь уже обрашается к конкретной строке - и именно она и заблокирована. на кой ему просматривать ещё 20ГБстрок, "чтобы блаблаблабла" ?
да, точно, можно не просматривать, но сейчас нет такого готового модуля, я смотрел http://www.postgresql.org/docs/9.2/static/pgrowlocks.html а он всю таблицу сканирует.
10 фев 14, 21:19    [15548453]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
alex_by_guest
Member

Откуда:
Сообщений: 10
Всем добрый день!
Аналогичный вопрос возник - возможно за прошедшие 6 (от начального поста) лет в постргресе таки появилась возможность узнать имя пользователя редактирующего строку в таблице? С использованием системных представлений?

Спасибо!
30 окт 20, 14:56    [22223579]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
Guzya
Member

Откуда:
Сообщений: 632
pg_stat_activity ?
30 окт 20, 21:39    [22223788]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
vyegorov
Member

Откуда: Рига
Сообщений: 1212
alex_by_guest,

https://github.com/dataegret/pg-utils/blob/master/sql/locktree.sql
30 окт 20, 22:21    [22223803]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
alex_by_guest
Member

Откуда:
Сообщений: 10
vyegorov,
О! Спасибо.
Беглым взглядом пробежался - это же запрос, который покажет взаимные блокировки?
Я наверно должен был уточнить - строка у меня лочится как select for update nowait.
Соответственно если этот запрос вернёт ошибку, что запись уже заблокирована, то нужно "мягко" вытащить запросом кто именно ее держит.
31 окт 20, 14:58    [22223974]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
vyegorov
Member

Откуда: Рига
Сообщений: 1212
alex_by_guest,

Этот запрос показывает блокировки в системе “со стороны”, он мониторинговый.
Посмотреть кто держит нужную вам запись можно запросом к pg_locks.
31 окт 20, 21:48    [22224139]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
alex_by_guest
Member

Откуда:
Сообщений: 10
vyegorov,
Благодарю Вас за ответ!
Я проверил данный запрос после блокировки записи из одной сессии.
В этом случае он, к сожалению, не возвращает ни одной строки.
Если, при открытой транзакции в первой сессии, выполнить select for update из другой сессии(перевести в состояние ожидания освобождения строки), то да - запрос работает и показывает текст запроса из второй сессии.

Т.е. открытым остается вопрос - как в postgresql проверить/докопаться какой пользователь "держит" запись в конкретной таблице не создавая конкурирующую блокировку? Т.е. на примере выше - ситуация когда у нас только одна начальная сессия.

Возможно ли это сделать через системные вьюхи?
Или может есть инструменты наподобие именованных транзакций в Oracle?

Или такое в postgresql невозможно в принципе?
Буду рад любой помощи в этом вопросе...
3 ноя 20, 15:55    [22225775]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
Maxim Boguk
Member

Откуда: Melbourne, Австралия
Сообщений: 4404
alex_by_guest,

>Т.е. открытым остается вопрос - как в postgresql проверить/докопаться какой пользователь "держит" запись в конкретной таблице не создавая конкурирующую блокировку?

Не возможно в принципе.


Если очень надо то в 2 коннекта решать...
в одном set lock_timeout '5s'; select for update
во второй если сразу не получилось for update взять - смотрим с кем он конфликтует (и выводим информацию).
каких то особых проблем с реализацией этого подхода я не вижу...


--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
3 ноя 20, 16:47    [22225816]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
vyegorov
Member

Откуда: Рига
Сообщений: 1212
alex_by_guest,

Блокировки на уровне записей не отслеживаются в системных вьюхах, вы представляете какой там объем данных может быть потенциально в базе на 10TB?
Поэтому блокировки показываются только тогда, когда кто-то начинает ждать.

В целом — не понятно какую задачу вы решить пытаетесь?..
3 ноя 20, 20:25    [22225971]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
alex_by_guest
Member

Откуда:
Сообщений: 10
vyegorov,

Ну тут скорее не объем базы важен, а количество редактирующих строки пользователей.
В общем в итоге таки решил задачу через ваш запрос по поиску блокировок. Сделал через pg_background. В рамках функции - создаем блокировку в новой сесии и выполняем запрос по поиску этой блокировки. После получения пользователя убиваем бэкграунд сессию.

Еще раз спасибо!
9 ноя 20, 15:01    [22228791]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
alex_by_guest
Member

Откуда:
Сообщений: 10
vyegorov,

PS. А задача весьма распространённая. Например дать возможность одному сотруднику найти того, кто "держит" нужный ему документ. Например кладовщик забыл сохранить накладную и ушел на обед/перекур/загул. А диспетчер ее выдать водителю не может. Соответственно перед ним встает вопрос - кого из пользователей пинать, кому звонить чтобы отпустил документ?
9 ноя 20, 15:07    [22228797]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
alex_by_guest
Member

Откуда:
Сообщений: 10
Maxim Boguk,

Да, в принципе так и сделал в итоге.
А про "невозможно" - в оракле, например, это решается именованными блокировками. Если не ошибаюсь начиная еще с версии 9i.
9 ноя 20, 15:19    [22228805]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
vyegorov
Member

Откуда: Рига
Сообщений: 1212
alex_by_guest,

Если у вас возникают такие ситуации, значит у вас однозначно есть долгие сессии в `idle in transaction` состоянии в базе.
Вместо того, чтобы городить поиск “кто заблокировал?” напишите скрипт для их отстрела или ограничьте настройками время `idle in transaction` до 5 минут.
Как, впрочем, и время обычных `active` сессий надо ограничить, скажем 30 минутами, всякие отчёты запускать от выделенного пользователя и для него сделать лимит больше, 2 часа к примеру.
9 ноя 20, 16:51    [22228885]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
Павел Лузанов
Member

Откуда:
Сообщений: 754
alex_by_guest

А про "невозможно" - в оракле, например, это решается именованными блокировками. Если не ошибаюсь начиная еще с версии 9i.

Речь о dbms_lock? Тогда в постгресе это рекомендательные блокировки.
9 ноя 20, 17:05    [22228898]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
Maxim Boguk
Member

Откуда: Melbourne, Австралия
Сообщений: 4404
alex_by_guest,

Кстати да как Виктор выше написал - это лечится установкой разумного idle in transaction timeout через крон или настройку базы.
Допустимая длина транзакции определяется из бизнес требований.


--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru

Сообщение было отредактировано: 10 ноя 20, 00:17
9 ноя 20, 23:37    [22229180]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
alex_by_guest
Member

Откуда:
Сообщений: 10
vyegorov
alex_by_guest,

Если у вас возникают такие ситуации, значит у вас однозначно есть долгие сессии в `idle in transaction` состоянии в базе.
Вместо того, чтобы городить поиск “кто заблокировал?” напишите скрипт для их отстрела или ограничьте настройками время `idle in transaction` до 5 минут.
Как, впрочем, и время обычных `active` сессий надо ограничить, скажем 30 минутами, всякие отчёты запускать от выделенного пользователя и для него сделать лимит больше, 2 часа к примеру.


Спасибо за совет, но предлагаемое вами решение в нашей ситуации неприемлемо.
"значит у вас однозначно есть долгие сессии в `idle in transaction` состоянии в базе." - на самом деле в этом нет ничего страшного или ненормального.

Вопрос был в том - как найти пользователя? Как уже написал ранее - мы эту задачу успешно решили через pg_background и locktree.sql.
Спасибо!
25 ноя 20, 13:19    [22238288]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
alex_by_guest
Member

Откуда:
Сообщений: 10
Павел Лузанов,
Интересная тема. Надо будет почитать.
Спасибо!
25 ноя 20, 13:20    [22238290]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
Maxim Boguk
Member

Откуда: Melbourne, Австралия
Сообщений: 4404
alex_by_guest
Павел Лузанов,
Интересная тема. Надо будет почитать.
Спасибо!


advisory locks обсуждались со всех сторон в начале этой темы.
у них есть свои плюсы и минусы но при аккуратном использовании - работают.

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
25 ноя 20, 14:12    [22238330]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
alex_by_guest
Member

Откуда:
Сообщений: 10
Maxim Boguk,

Да, но там указали, что имя пользователя все равно не получится выдернуть - поэтому не стал заострять внимание.
25 ноя 20, 18:25    [22238451]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
vyegorov
Member

Откуда: Рига
Сообщений: 1212
alex_by_guest

"значит у вас однозначно есть долгие сессии в `idle in transaction` состоянии в базе." - на самом деле в этом нет ничего страшного или ненормального.


это точно ненормально! `idle in transaction` говорит о том, что приложение не даёт базе никакой работы при открытой транзакции.
такая ситуация не должна возникать, транзакции не для этого.
наличие таких сессий показывает либо проблемы в коде (некорректная работа с транзакциями), либо нехватку ресурсов на стороне приложения (перегрузка по CPU) либо проблемы с третьими сервисами, куда приложение ходит по сети удерживая открытую транзакцию.
25 ноя 20, 20:13    [22238520]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли узнать какой пользователь заблокировал запись в таблице?  [new]
alex_by_guest
Member

Откуда:
Сообщений: 10
vyegorov,
Вы слишком категоричны.

"наличие таких сессий показывает либо проблемы в коде (некорректная работа с транзакциями), либо нехватку ресурсов на стороне приложения (перегрузка по CPU) либо проблемы с третьими сервисами, куда приложение ходит по сети удерживая открытую транзакцию." - нет. ничего из перечисленного в нашем случае нет. всё в порядке :)

Не хочу вдаваться в подробности и в стопицотый раз развязывать по этому поводу холивар - просто поверьте, что это вполне себе рабочая ситуация.

Сообщение было отредактировано: 26 ноя 20, 12:54
26 ноя 20, 12:52    [22238792]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: 1 2      [все]
Все форумы / PostgreSQL Ответить