refactor(mysql): 适配PXC严格模式,替换全局锁方案
重构MySQL迁移逻辑,新增acquireMigrationLock适配Percona XtraDB Cluster的pxc_strict_mode限制,将原有的GET_LOCK迁移锁替换为更兼容的方案,同时为各迁移流程添加快速检查路径减少锁竞争
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
//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
|
||||
}
|
||||
Reference in New Issue
Block a user