refactor(mysql): 适配PXC严格模式,替换全局锁方案

重构MySQL迁移逻辑,新增acquireMigrationLock适配Percona XtraDB Cluster的pxc_strict_mode限制,将原有的GET_LOCK迁移锁替换为更兼容的方案,同时为各迁移流程添加快速检查路径减少锁竞争
This commit is contained in:
Austin
2026-09-20 14:52:01 +08:00
parent 753a04ed12
commit b2e8b64c0b
4 changed files with 105 additions and 29 deletions
+26 -6
View File
@@ -5,7 +5,6 @@ package mysql
import (
"context"
"database/sql"
"errors"
"fmt"
"strings"
@@ -32,14 +31,35 @@ func ensureUserIdentitySchema(db *sqlx.DB) error {
}
defer conn.Close()
var locked sql.NullInt64
if err = conn.QueryRowContext(ctx, "SELECT GET_LOCK("+userIdentityMigrationLock+", 60)").Scan(&locked); err != nil {
// Fast path: the last two steps of this migration drop the legacy im_usertags
// table and the im_users.tags column. If both are already gone, the migration
// has fully run (or the database was created fresh) and no lock is needed.
stale := false
if exists, err := identityTableExists(ctx, conn, "im_usertags"); err != nil {
return err
} else if exists {
stale = true
}
if !stale {
if exists, err := identityColumnExists(ctx, conn, "im_users", "tags"); err != nil {
return err
} else if exists {
stale = true
}
}
if !stale {
return nil
}
// PXC strict-mode clusters prohibit GET_LOCK; acquireMigrationLock falls back
// to lock-free execution in that case. The migration body is idempotent.
_, unlock, err := acquireMigrationLock(ctx, conn, userIdentityMigrationLock)
if err != nil {
return err
}
if !locked.Valid || locked.Int64 != 1 {
return errors.New("mysql: timed out waiting for user identity migration lock")
if unlock != nil {
defer unlock()
}
defer conn.ExecContext(ctx, "SELECT RELEASE_LOCK("+userIdentityMigrationLock+")")
usersExist, err := identityTableExists(ctx, conn, "im_users")
if err != nil || !usersExist {