LINUX.ORG.RU

Конкурентное обновление таблицы с ресурсами

 , ,


0

2

Вкратце опишу задачу. У компании есть клиенты, от имени которых она ведет переписку с третьими сервисами используя google workspace.

У каждого email эккаунта в google workspace можно завести алиас с помощью api, и использовать его в дальнейшем для конкретной переписки. После окончания переписки алиас можно просто удалить с помощью того же api. Это нужно потому, что есть лимит на количество алиасов для каждого email эккаунта в google workspace.

Бэк реализован на python с использованием sqlalchemy. БД - postgres.

Поэтому возникла идея создать две таблицы. Одну - со списком имеющихся email эккаунтов. И вторую, где будет список использующихся в данный момент алиасов для каждого email.

То есть во второй таблице (aliases) будут следующие поля: id, email, alias_email.

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

То есть делаем запрос вроде

select email, count(*)
from aliases
group by email

А затем выбираем из результата любой email, у которого не превышен лимит и вставляем новую запись со свежим алиасом для этого email в эту же таблицу. Ну и создаем алиас помощью google workspace api.

При окончании переписки просто удаляем запись с алиасом из таблицы и удаляем с помощью api сам алиас.

Возникает ситуация гонок, надо бы на момент выбора алиаса лочить таблицу aliases.

Можно ли это сделать с помощью алхимии? И какие есть альтернативы в подобной ситуации, когда есть конкурентные запросы к таблице в целом, а не к конкретным записям?


Ответ на: комментарий от anonymous

В том то и дело, что мы можем запретить с помощью for update именно update конкретных записей, а не вставку новых на момент выбора алиаса.

Может можно было бы использовать этот механизм (select for update) при какой-то другой схеме данных для данной задачи, но пока не понимаю, как.

C
() автор топика
Ответ на: комментарий от masa

Покажу пример таблицы, чтобы было наглядней. Предположим, что лимит у нас 3 алиаса на email.

-----------------------------------------------------------
|. email                   |           alias_email        |
|---------------------------------------------------------|
| corporateemail1@gmail.com|          vasya@gmail.com     |
| corporateemail1@gmail.com|          lesha@gmail.com     |
| corporateemail1@gmail.com|          misha@gmail.com     |
| corporateemail2@gmail.com|          sanya@gmail.com     |
| corporateemail2@gmail.com|          vova@gmail.com      |
-----------------------------------------------------------

Отсюда мы сделаем запрос с group by, узнаем, что у corporateemail2@gmail.com есть еще не занятый алиас и вставим новую запись для этого email

| corporateemail2@gmail.com|          kostya@gmail.com     |

То есть по идее надо бы запретить вставку и удаление записей на момент выбора алиаса.

C
() автор топика
Ответ на: комментарий от gruy

SERIALIZABLE - неплохое решение, но как я понимаю, оно повлияет и на все остальные запросы к другим таблицам, то есть сильно уменьшит производительность системы в целом. Неужели создавать два коннекшна с разным уровнем изоляции - одно для для работы с обычными таблицами и другое для таблицы с алиасами?

C
() автор топика

id, email, alias_email

Ты сейчас просто послал нафиг третью нормальную форму.

emails: id, email aliases: id, email_id, alias

Не хочешь городить контекст менеджер который бы через текущий коннект дергал сырой SQL с блокировкой - используй распределенный мьютекс в коде.

anonymous
()
Ответ на: комментарий от anonymous

Ты сейчас просто послал нафиг третью нормальную форму.

emails: id, email aliases: id, email_id, alias

Да, я просто не стал до конца нормализовать таблицы. Скорей всего так и сделаю, как ты сказал - с email_id в таблице aliases.

Не хочешь городить контекст менеджер который бы через текущий коннект дергал сырой SQL с блокировкой - используй распределенный мьютекс в коде.

У меня есть мысль создать хранимую процедуру в postgres - там вроде можно сделать lock таблице aliases. Гляну насчет сырого sql, раз там можно тоже lock указать.

C
() автор топика

какая жесть в ответах…

  1. от дублей в БД адекватно защищает только уникальный индекс за счет своей специфичной структуры
  2. unique constraint от дублей тоже защищает, но здесь начинаются истории про реализацию конкретной СУБД, т.е. unique constraint можно строить как на обычных индексах, так и вообще без индексов, но цена вопроса здесь определяется уровнем эскалации блокировок, условно со стороны стандарта ничего не препятствует бахнуть на таблицу unique constraint, но результат будет такой, что каждая вставка или обновление будет захватывать эксклюзивную блокировку на таблицу, чего обычно не ожидается, поэтому СУБД обычно для неискушенных разработчиков «не различают» unique constraint и unique index, т.е. задание constraint будет создавать или требовать наличие индекса, а создание индекса само под собой подразумевает существование constraint, но разница есть
  3. в каких-то БД есть возможности создания «бизнесовых блокировок», например : https://www.postgresql.org/docs/current/explicit-locking.html#ADVISORY-LOCKS - но все реализации что существуют настолько всраты, что лучше их обходить стороной

т.е. да:

  • там где требуется уникальность нужно использовать уникальный индекс
  • с ошибками придется либо мириться, либо уметь обходить (например расставлять сейвпойнты, но там тоже какая-то разумность требуется, например в PostgreSQL там все очень плохо с этим)
borisych ★★★★★
()
Ответ на: комментарий от C

Пошли нафиг третью нормальную форму ©.

--------------------------------------------------------------------------------------
| email                    |  alias_email1      | alias_email2    | alias_email3     |
--------------------------------------------------------------------------------------
| corporateemail1@gmail.com|  vasya@gmail.com   | lesha@gmail.com | misha@gmail.com  |
| corporateemail2@gmail.com|  sanya@gmail.com   |                 | vova@gmail.com   |
--------------------------------------------------------------------------------------

Правда, если лимит на количество алиасов потом будет изменен, тебя ждут проблемы.

Aceler ★★★★★
()