Files
im_server/server/db/mysql/migration_lock.go
T
Austin b2e8b64c0b refactor(mysql): 适配PXC严格模式,替换全局锁方案
重构MySQL迁移逻辑,新增acquireMigrationLock适配Percona XtraDB Cluster的pxc_strict_mode限制,将原有的GET_LOCK迁移锁替换为更兼容的方案,同时为各迁移流程添加快速检查路径减少锁竞争
2026-09-20 14:52:01 +08:00

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
}