Блокировка добавления строк с определенным идентификатором внешнего ключа в Postgres/SQLAlchemy

#python #postgresql #sqlalchemy

Вопрос:

Допустим, у меня есть таблица, похожая на эту:

 PERSON:

id | person_name 

ITEM:

id | name | person_id
 

Элементы person_id-это FK для человека.

У меня есть операция, которая добавляет товары оптом к человеку. Но я хочу убедиться, что никакие другие процессы не добавляют элементы одновременно к этому человеку, не блокируя всю таблицу person.

Есть ли способ достичь этого в Постгресе? И лучше код для достижения этой цели с помощью Python SQLAlchemy?

Ответ №1:

Я думаю, вы хотите использовать SELECT FOR UPDATE via Query.with_for_update . Просто предупреждение, хотя вы должны быть осторожны, чтобы всегда блокировать в одном и том же порядке и одним и тем же способом, иначе вы можете легко заблокировать свои потоки. Т. е. Не блокируйте таблицу A, затем заблокируйте таблицу B в одной области кода и заблокируйте таблицу B, а затем таблицу A в другой области кода, потому что это может привести к взаимоблокировке.

 # Other calls to SELECT FOR UPDATE will BLOCK when they try to lock this person
person = session.query(Person).with_for_update().filter(Person.id == 5).first()

# Update person items here
for item in person.items[0:3]:
    session.delete(item)

session.commit()
 

https://docs.sqlalchemy.org/en/14/orm/query.html?выделите=for_update#sqlalchemy.orm.Query.with_for_update

https://www.postgresql.org/docs/9.0/sql-select.html#SQL-FOR-UPDATE-SHARE

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

1. Большое вам спасибо 🙂 это как раз то, что мне было нужно

Ответ №2:

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

 select * from person where id=? for update