Browse Source
业务容器里 gateway/home/api/mcp/timer 同时拉起,echomeet_record 由 home 的 echomeet 模块与 api 模块 同时 AutoMigrate。AutoMigrate 是「查列在不在 → ALTER」两步非原子,两边都查到缺列、都去加, 后到者报 1060 Duplicate column,模块初始化失败 panic,home 的接口全部 code:11。 2026-09-26 正式服发 0.2.9(新加 computeuser/computedevices 两列)时 api 抢先加成功,home 挂了几分钟, 已回滚 0.2.8 恢复。测试服当时是先后顺序错开才没撞上。 CreateTable 遇到 1050/1060/1061(对方已建好表/列/索引)时等 0.5s/1s 再同步,最多 3 次; 其它错误照旧直接返回。postgres 的 CreateTable 表已存在即跳过、不加列,没有这个竞态,未改。 验证:go build/vet 通过,TestIsConcurrentDDLConflict 通过。 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>main
2 changed files with 60 additions and 1 deletions
@ -0,0 +1,26 @@ |
|||||
|
package mysql |
||||
|
|
||||
|
import ( |
||||
|
"errors" |
||||
|
"fmt" |
||||
|
"testing" |
||||
|
|
||||
|
mysqldrv "github.com/go-sql-driver/mysql" |
||||
|
) |
||||
|
|
||||
|
// 只有「对方已经建好了」这类冲突才重试;其余错误(权限、语法、连接断开)照旧直接返回。
|
||||
|
func TestIsConcurrentDDLConflict(t *testing.T) { |
||||
|
cases := map[error]bool{ |
||||
|
&mysqldrv.MySQLError{Number: 1060, Message: "Duplicate column name 'computeuser'"}: true, |
||||
|
&mysqldrv.MySQLError{Number: 1050, Message: "Table already exists"}: true, |
||||
|
&mysqldrv.MySQLError{Number: 1061, Message: "Duplicate key name"}: true, |
||||
|
fmt.Errorf("wrap: %w", &mysqldrv.MySQLError{Number: 1060}): true, |
||||
|
&mysqldrv.MySQLError{Number: 1142, Message: "ALTER command denied"}: false, |
||||
|
errors.New("driver: bad connection"): false, |
||||
|
} |
||||
|
for err, want := range cases { |
||||
|
if got := isConcurrentDDLConflict(err); got != want { |
||||
|
t.Errorf("%v → %v, want %v", err, got, want) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue