Comments 32
UFO just landed and posted this here
— Как проверять, когда со строкой работают несколько пользователей? Какие варианты есть?
В MSSQL есть столбец типа timestamp, в pg можно заюзать xmin, например. Отдаём на форму его значение, при апдейте проверяем не только ключ, но и сравниваем с xmin. Если кто-то изменил строчку — не обновим ничего, сообщаем пользователю (а он уж пусть решает, насильно перенакатить, бросить всё, попытаться смёржить).
0
Не надо xmin. Это внутренная механика, не используйте ее в своих целях (если, конечно, не хочется развлечений при обновлениях). Не хочется проверять все поля — сделайте свой номер версии.
+1
Ну а что делать, если в PG нет встроенных средств :( Если использование сущности ограничено, то можно и своё версионирование написать, но потом придёт какой-нибудь разработчик, и забудет в каком-нибудь апдейте проинкрементить версию. В результате всё замечательно «сломается», хотя работать будет, но будет бага вида «у меня пропали данные», которую вообще не возможно будет отследить.
Уж лучше всё упадёт при обновлении и можно накрыть это костылями, чем будет странно себя вести из-за ошибки программиста в каком-нибудь второстепенном модуле.
Уж лучше всё упадёт при обновлении и можно накрыть это костылями, чем будет странно себя вести из-за ошибки программиста в каком-нибудь второстепенном модуле.
0
Простите, а какие встроенные средства вы хотели бы видеть? Чем вариант с хешом от всех колонок не нравится?
0
В MSSQL есть столбец типа timestamp (и нет, там не время). В результате при любом обновлении записи значение этого столбца меняется автоматически. Ничего не надо считать ручками, нельзя забыть его обновить. В postgre для этих целей можно использовать xmin, но он считается не очень труЪ способом.
0
В Oracle есть
неужели в Pg нет ничего столь же удобного?
select for update
неужели в Pg нет ничего столь же удобного?
0
Не стоит это использовать для данной задачи.
Представьте, пользователь открывает форму на редактирование и… уходит на обед. Строчка залочена. Больше никто не может ничего с ней сделать.
Представьте, пользователь открывает форму на редактирование и… уходит на обед. Строчка залочена. Больше никто не может ничего с ней сделать.
+1
Так незачем держать транзакцию открытой когда пользователь открыл форму. Транзакцию открывают когда пользователь сохраняет форму.
select for update
блокирует чтение строки другими транзакциями.0
А смысл этого действия? Форму открыли два пользователя в 12:00. Редактируют, первый сохранил в 12:05, второй в 12:10 и затёр все действия первого. Чем нам в этой ситуации поможет SELECT FOR UPDATE?
+1
Ну что вы, чтение не блокируется. Блокируется только изменение.
Но транзакцию, конечно, все равно не надо держать открытой.
Но транзакцию, конечно, все равно не надо держать открытой.
0
select for update не блокирует чтение (т.е. select). Он блокирует запись или select for update другими пользователями.
0
Собственно для задачи гарантированного избавления от совместных правок это и придумано.
Как мне показалось в докладе обсуждается именно проблема совместных правок.
Впрочем топик про Pg. И, судя по всему, в нем нельзя на уровне базы гарантировать неизменяемость данных другими транзакциями на необходимое время.
Как мне показалось в докладе обсуждается именно проблема совместных правок.
Впрочем топик про Pg. И, судя по всему, в нем нельзя на уровне базы гарантировать неизменяемость данных другими транзакциями на необходимое время.
0
Ну это как бы логично — кто первый успел, того и тапки. Хуже будет, если пользователь 1 открыл форму и ушёл на обед. Пользователь 2 открыл ту же форму, внёс изменения и записал данные. Пользователь 1 вернулся с обеда, внёс в форму данные и при попытке записать данные система говорит, что пользователь 2 уже изменил данные. Поэтому нужно переоткрыть форму (перечитать данные из бд) и все, что вносил пользователь 1 в форму, нужно теперь внести заново
0
Хуже будет, если пользователь 1 открыл форму и ушёл на обед
Что вы тут предлагаете? Не давать редактировать форму никому, или просто сделать хороший код, который это как-то обрабатывает. Второй подход отличный, но очень дорогой в плане времени программистов (форм много, все разные, ситуация не очень частая).
0
Это хороший вопрос. Я скажу лишь как сейчас реализовано, например в 1С. До недавнего времени, если пользователь открыл форму документа, то никто больше не мог работать с этим документом. Теперь идет проверка самой платформой (не на уровне бд) признака модифицированности. Если пользователь внес изменения и не записал их — просмотр и редактирование документа по прежнему невозможно, а если модифицированности формы нет, то другие пользователи могут работать с документом. То есть, если пользователь 1 открыл форму и ушел на обед, при этом не внеся никаких правок, то пользователь 2 спокойно может работать, если правки пользователь 1 успел сделать — то пользователь 2 работать с документом не сможет
0
Это плохое решение. Пользователь может не на обед, а куда-то убежать по делам (любимый хомячок простудился) и банально позвонить другому с просьбой доделать. Может просто случайно нажать какую-то кнопку (сохранять не планировал) и уйти домой. В небольшой организации это может решиться организационными методами и пенделями работникам, но больше шансов, что пендели получать разработчики.
0
Мы, разработчики, нередко полагаем, что можем программным методом направить, так сказать, пользователей на путь истинный. Написать свой «ИИ» чтобы данные вводились только корректные и бизнес процесс шёл идеально. Но в реальности самыми действенными способами оказываются именно организационные. Главное не забывать, что лучше всего на человека влияет другой человек, а любое ограничение системы пользователь найдёт как обойти
0
— Как проверять, когда со строкой работают несколько пользователей? Какие варианты есть?
— Во-первых, можно перед показом строки в форме вЫчитать значения всех колоночек и убедиться, что они не поменялись. Второй вариант, более удобный: высчитать хэш на всех
колонках, тем более, что колонки там могут быть большие и толстые. А хэш не такой большой.
Серьезно, это вопрос на конференции?
-2
Абсолютно серьезно. А что такого? Вон выше select for update предлагают.
0
Поправьте меня, может, я не понимаю.
Все эти select for update — это же про то, как блокировать данные в транзакции при изменении (т.е. сначала select, какая-то обработка, тут же update). А не про то, что Вася открыл окно, select-ом for update выбрал и заблокировал строку на длительное время, а потом через час сделал update.
В вопросе речь идет про non-lock concurrency control. Это когда на уровне логики приложения проверяется, не изменена ли запись кем-то относительно момента, когда мы ее вывели в окно. И это не в транзакции.
Мне кажется, это не вопрос о PostgreSQL.
Все эти select for update — это же про то, как блокировать данные в транзакции при изменении (т.е. сначала select, какая-то обработка, тут же update). А не про то, что Вася открыл окно, select-ом for update выбрал и заблокировал строку на длительное время, а потом через час сделал update.
В вопросе речь идет про non-lock concurrency control. Это когда на уровне логики приложения проверяется, не изменена ли запись кем-то относительно момента, когда мы ее вывели в окно. И это не в транзакции.
Мне кажется, это не вопрос о PostgreSQL.
0
Партиции для архивных данных работают прекрасно. Делал так, например, базу ФИАС разбивая на партиции по регионам. Рекурсивный CTE вытаскивает данные очень быстро.
0
у нас еще есть max idle in transaction
Возможно, имелось ввиду idle_in_transaction_session_timeout?
+1
Sign up to leave a comment.
Типичные ошибки при работе с PostgreSQL. Часть 2