Sobes.tech
Middle

Un signal est arrivé, et immédiatement 3 groupes y ont répondu en même temps, mais nous devons n'envoyer qu'un seul groupe. Comment faire cela au niveau des transactions dans la base de données?

sobes.tech IA

Réponse de l'IA

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

Например, в транзакции:

  1. Начинается транзакция.
  2. Выполняется запрос с блокировкой строки или записи, отвечающей за обработку сигнала (например, SELECT ... FOR UPDATE).
  3. Проверяется, была ли уже отправлена группа по этому сигналу.
  4. Если нет — выбирается одна из групп и фиксируется факт отправки.
  5. Транзакция коммитится.

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

Пример на Go с использованием базы PostgreSQL и пакета database/sql:

// tx, err := db.Begin()
// defer tx.Rollback()
// row := tx.QueryRow("SELECT sent FROM signals WHERE id = $1 FOR UPDATE", signalID)
// var sent bool
// err = row.Scan(&sent)
// if err != nil {
//     return err
// }
// if !sent {
//     // Отправляем группу
//     _, err = tx.Exec("UPDATE signals SET sent = true WHERE id = $1", signalID)
//     if err != nil {
//         return err
//     }
// }
// return tx.Commit()

Это классический подход для обеспечения атомарности и предотвращения гонок при параллельной обработке.