From 08c5431c0b9af9ca45395665dde5f0eee4a4df6a Mon Sep 17 00:00:00 2001 From: Cenk Alti Date: Tue, 15 Sep 2020 00:55:51 +0300 Subject: [PATCH] avoid deadlock on instances table when running multiple instances --- internal/table/table.go | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/internal/table/table.go b/internal/table/table.go index 1ff34c3..fb3c15e 100644 --- a/internal/table/table.go +++ b/internal/table/table.go @@ -397,23 +397,16 @@ func (t *Table) Instances(ctx context.Context) (int64, error) { // and clears out any inactive instances from the list, such as // instances that were unable to call DeleteInstance during shutdown. func (t *Table) UpdateInstance(ctx context.Context, id uint32) error { - // The MySQL driver doesn't support multiple statements in a single Exec if they contain placeholders. - // That's why we use a transaction. - tx, err := t.db.BeginTx(ctx, nil) - if err != nil { - return err - } - defer tx.Rollback() // nolint: errcheck now := t.Clk.NowUTC() s1 := "INSERT INTO " + t.name + "_instances(id, updated_at) VALUES (" + strconv.FormatUint(uint64(id), 10) + ",IFNULL(CAST(? as DATETIME), UTC_TIMESTAMP())) ON DUPLICATE KEY UPDATE updated_at=IFNULL(?, UTC_TIMESTAMP())" - if _, err = tx.ExecContext(ctx, s1, now, now); err != nil { + if _, err := t.db.ExecContext(ctx, s1, now, now); err != nil { return err } s2 := "DELETE FROM " + t.name + "_instances WHERE updated_at < IFNULL(CAST(? as DATETIME), UTC_TIMESTAMP) - INTERVAL 1 MINUTE" - if _, err = tx.ExecContext(ctx, s2, now); err != nil { + if _, err := t.db.ExecContext(ctx, s2, now); err != nil { return err } - return tx.Commit() + return nil } // DeleteInstance removes an entry from the list of active instances.