重构MySQL迁移逻辑,新增acquireMigrationLock适配Percona XtraDB Cluster的pxc_strict_mode限制,将原有的GET_LOCK迁移锁替换为更兼容的方案,同时为各迁移流程添加快速检查路径减少锁竞争
37 lines
1.2 KiB
Go
37 lines
1.2 KiB
Go
//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
|
|
}
|