diff --git a/agent/app/dto/database.go b/agent/app/dto/database.go index ff75e9cb787a..154398c44744 100644 --- a/agent/app/dto/database.go +++ b/agent/app/dto/database.go @@ -38,6 +38,7 @@ type MysqlDBInfo struct { From string `json:"from"` MysqlName string `json:"mysqlName"` Format string `json:"format"` + Collation string `json:"collation"` Username string `json:"username"` Password string `json:"password"` Permission string `json:"permission"` diff --git a/agent/init/migration/migrations/init.go b/agent/init/migration/migrations/init.go index fd7432b80cf9..41984a49acfc 100644 --- a/agent/init/migration/migrations/init.go +++ b/agent/init/migration/migrations/init.go @@ -728,8 +728,31 @@ var AddGPUMonitor = &gormigrate.Migration{ } var UpdateDatabaseMysql = &gormigrate.Migration{ - ID: "20251125-update-database-mysql", - Migrate: func(tx *gorm.DB) error { - return tx.AutoMigrate(&model.DatabaseMysql{}) + ID: "20251126-update-database-mysql", + Migrate: func(tx *gorm.DB) error { + if err := tx.AutoMigrate(&model.DatabaseMysql{}); err != nil { + return err + } + var data []model.DatabaseMysql + _ = tx.Where("1 = 1").Find(&data).Error + for _, item := range data { + if len(item.Collation) == 0 { + collation := "" + switch item.Format { + case "utf8": + collation = "utf8_general_ci" + case "utf8mb4": + collation = "utf8mb4_general_ci" + case "gbk": + collation = "gbk_chinese_ci" + case "big5": + collation = "big5_chinese_ci" + default: + collation = "utf8mb4_general_ci" + } + _ = tx.Model(&model.DatabaseMysql{}).Where("id = ?", item.ID).Updates(map[string]interface{}{"collation": collation}).Error + } + } + return nil }, } diff --git a/agent/utils/mysql/client/info.go b/agent/utils/mysql/client/info.go index fb6cbda246cb..5b6ffb6f0446 100644 --- a/agent/utils/mysql/client/info.go +++ b/agent/utils/mysql/client/info.go @@ -101,6 +101,7 @@ type SyncDBInfo struct { From string `json:"from"` MysqlName string `json:"mysqlName"` Format string `json:"format"` + Collation string `json:"collation"` Username string `json:"username"` Password string `json:"password"` Permission string `json:"permission"` diff --git a/agent/utils/mysql/client/local.go b/agent/utils/mysql/client/local.go index 4ed8995daf83..ce0caaa90b86 100644 --- a/agent/utils/mysql/client/local.go +++ b/agent/utils/mysql/client/local.go @@ -33,6 +33,9 @@ func NewLocal(command []string, dbType, containerName, password, database string func (r *Local) Create(info CreateInfo) error { createSql := fmt.Sprintf("create database `%s` default character set %s collate %s", info.Name, info.Format, info.Collation) + if len(info.Collation) == 0 { + createSql = fmt.Sprintf("create database `%s` default character set %s", info.Name, info.Format) + } if err := r.ExecSQL(createSql, info.Timeout); err != nil { if strings.Contains(strings.ToLower(err.Error()), "error 1007") { return buserr.New("ErrDatabaseIsExist") @@ -287,13 +290,13 @@ func (r *Local) Recover(info RecoverInfo) error { func (r *Local) SyncDB(version string) ([]SyncDBInfo, error) { var datas []SyncDBInfo - lines, err := r.ExecSQLForRows("SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME FROM information_schema.SCHEMATA", 300) + lines, err := r.ExecSQLForRows("SELECT SCHEMA_NAME, DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM information_schema.SCHEMATA", 300) if err != nil { return datas, err } for _, line := range lines { parts := strings.Fields(line) - if len(parts) != 2 { + if len(parts) != 3 { continue } if parts[0] == "SCHEMA_NAME" || parts[0] == "information_schema" || parts[0] == "mysql" || parts[0] == "performance_schema" || parts[0] == "sys" || parts[0] == "__recycle_bin__" || parts[0] == "recycle_bin" { @@ -304,6 +307,7 @@ func (r *Local) SyncDB(version string) ([]SyncDBInfo, error) { From: "local", MysqlName: r.Database, Format: parts[1], + Collation: parts[2], } userLines, err := r.ExecSQLForRows(fmt.Sprintf("select user,host from mysql.db where db = '%s'", parts[0]), 300) if err != nil { diff --git a/agent/utils/mysql/client/remote.go b/agent/utils/mysql/client/remote.go index 2e096821b1b2..86ebc980af39 100644 --- a/agent/utils/mysql/client/remote.go +++ b/agent/utils/mysql/client/remote.go @@ -44,6 +44,9 @@ func NewRemote(db Remote) *Remote { func (r *Remote) Create(info CreateInfo) error { createSql := fmt.Sprintf("create database `%s` default character set %s collate %s", info.Name, info.Format, info.Collation) + if len(info.Collation) == 0 { + createSql = fmt.Sprintf("create database `%s` default character set %s", info.Name, info.Format) + } if err := r.ExecSQL(createSql, info.Timeout); err != nil { if strings.Contains(strings.ToLower(err.Error()), "error 1007") { return buserr.New("ErrDatabaseIsExist") @@ -311,15 +314,15 @@ func (r *Remote) Recover(info RecoverInfo) error { func (r *Remote) SyncDB(version string) ([]SyncDBInfo, error) { var datas []SyncDBInfo - rows, err := r.Client.Query("select schema_name, default_character_set_name from information_schema.SCHEMATA") + rows, err := r.Client.Query("select schema_name, default_character_set_name, default_collation_name from information_schema.SCHEMATA") if err != nil { return datas, err } defer rows.Close() for rows.Next() { - var dbName, charsetName string - if err = rows.Scan(&dbName, &charsetName); err != nil { + var dbName, charsetName, collation string + if err = rows.Scan(&dbName, &charsetName, &collation); err != nil { return datas, err } if dbName == "information_schema" || dbName == "mysql" || dbName == "performance_schema" || dbName == "sys" || dbName == "__recycle_bin__" || dbName == "recycle_bin" { @@ -330,6 +333,7 @@ func (r *Remote) SyncDB(version string) ([]SyncDBInfo, error) { From: "remote", MysqlName: r.Database, Format: charsetName, + Collation: collation, } userRows, err := r.Client.Query("select user,host from mysql.db where db = ?", dbName) if err != nil { diff --git a/frontend/src/views/database/mysql/create/index.vue b/frontend/src/views/database/mysql/create/index.vue index 28de96a9495e..83a4b71aa676 100644 --- a/frontend/src/views/database/mysql/create/index.vue +++ b/frontend/src/views/database/mysql/create/index.vue @@ -15,7 +15,7 @@ - + {{ $t('database.collationHelper', [form.format]) }}