Back to questions
Senior
3
Задача на проектирование: есть система для групп быстрого реагирования. Пришёл сигнал, и сразу три группы на него откликнулись одновременно. Нужно послать только одну группу. Как это сделать на уровне транзакций в базе данных?
Companies where asked
purrweb
Answer from AI
sobes.tech AI
Для решения задачи с одновременным откликом нескольких групп и выбором только одной на уровне транзакций в базе данных можно использовать механизм блокировок и уникальных ограничений.
Подход:
- Создайте таблицу, например,
signal_assignments, где хранится информация о том, какая группа назначена на сигнал. - При получении сигнала каждая группа пытается вставить запись с уникальным ключом по сигналу (например,
signal_idс уникальным индексом). - Первая транзакция, которая успешно вставит запись, «захватывает» сигнал.
- Остальные транзакции при попытке вставки получат ошибку уникального ограничения и должны откатиться или повторить попытку.
Пример на SQL:
CREATE TABLE signal_assignments (
signal_id UUID PRIMARY KEY,
group_id UUID NOT NULL
);
При обработке сигнала в транзакции:
BEGIN;
INSERT INTO signal_assignments(signal_id, group_id) VALUES (:signal_id, :group_id);
COMMIT;
Если вставка не удалась из-за уже существующей записи, значит сигнал уже назначен другой группе.
В Go с использованием транзакций:
func assignGroup(db *sql.DB, signalID, groupID string) error {
tx, err := db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
_, err = tx.Exec(`INSERT INTO signal_assignments(signal_id, group_id) VALUES ($1, $2)`, signalID, groupID)
if err != nil {
// Ошибка уникального ограничения — сигнал уже назначен
return err
}
return tx.Commit()
}
Таким образом, на уровне базы данных гарантируется, что только одна группа будет назначена на сигнал, несмотря на одновременные попытки.