//go:build mysql // +build mysql package mysql import ( "context" "database/sql" "errors" "github.com/jmoiron/sqlx" ) // acquireMigrationLock wraps SELECT GET_LOCK so that schema migrations keep // working on Percona XtraDB Cluster where pxc_strict_mode=ENFORCING prohibits // named locks: instead of failing, locked=false is returned and the caller // proceeds without the lock. This is safe because Galera's total order // isolation serializes DDL across the cluster, and every migration using this // helper is idempotent: steps are guarded by existence checks, so concurrent // runs at worst fail with duplicate-key errors and are retried on the next // startup. func acquireMigrationLock(ctx context.Context, conn *sqlx.Conn, lockExpr string) (locked bool, unlock func(), err error) { var held sql.NullInt64 if err = conn.QueryRowContext(ctx, "SELECT GET_LOCK("+lockExpr+", 60)").Scan(&held); err != nil { if isPXCStrictModeNamedLockError(err) { return false, nil, nil } return false, nil, err } if !held.Valid || held.Int64 != 1 { return false, nil, errors.New("mysql: timed out waiting for schema migration lock") } return true, func() { conn.ExecContext(ctx, "SELECT RELEASE_LOCK("+lockExpr+")") }, nil }