Просмотр исходного кода

feat(database): enhance MySQL support for Chinese characters

- Added a check for MySQL charset/collation to ensure compatibility with Chinese characters during database initialization.
- Updated SQLite busy timeout from 5000ms to 30000ms for improved performance.
- Removed commented-out PostgreSQL migration logic for clarity.
CaIon 4 месяцев назад
Родитель
Сommit
41cb01bac9
2 измененных файлов с 65 добавлено и 4 удалено
  1. 1 1
      common/database.go
  2. 64 3
      model/main.go

+ 1 - 1
common/database.go

@@ -12,4 +12,4 @@ var LogSqlType = DatabaseTypeSQLite // Default to SQLite for logging SQL queries
 var UsingMySQL = false
 var UsingClickHouse = false
 
-var SQLitePath = "one-api.db?_busy_timeout=5000"
+var SQLitePath = "one-api.db?_busy_timeout=30000"

+ 64 - 3
model/main.go

@@ -196,6 +196,12 @@ func InitDB() (err error) {
 			db = db.Debug()
 		}
 		DB = db
+		// MySQL charset/collation startup check: ensure Chinese-capable charset
+		if common.UsingMySQL {
+			if err := checkMySQLChineseSupport(DB); err != nil {
+				panic(err)
+			}
+		}
 		sqlDB, err := DB.DB()
 		if err != nil {
 			return err
@@ -230,6 +236,12 @@ func InitLogDB() (err error) {
 			db = db.Debug()
 		}
 		LOG_DB = db
+		// If log DB is MySQL, also ensure Chinese-capable charset
+		if common.LogSqlType == common.DatabaseTypeMySQL {
+			if err := checkMySQLChineseSupport(LOG_DB); err != nil {
+				panic(err)
+			}
+		}
 		sqlDB, err := LOG_DB.DB()
 		if err != nil {
 			return err
@@ -258,9 +270,9 @@ func migrateDB() error {
 
 	dropIndexIfExists("vendors", "uk_vendor_name") // 新版复合索引名称(若已存在)
 	dropIndexIfExists("vendors", "name")           // 旧版列级唯一索引名称
-	if !common.UsingPostgreSQL {
-		return migrateDBFast()
-	}
+	//if !common.UsingPostgreSQL {
+	//	return migrateDBFast()
+	//}
 	err := DB.AutoMigrate(
 		&Channel{},
 		&Token{},
@@ -373,6 +385,55 @@ func CloseDB() error {
 	return closeDB(DB)
 }
 
+// checkMySQLChineseSupport ensures the MySQL connection and current schema
+// default charset/collation can store Chinese characters. It allows common
+// Chinese-capable charsets (utf8mb4, utf8, gbk, big5, gb18030) and panics otherwise.
+func checkMySQLChineseSupport(db *gorm.DB) error {
+	// Read session/server variables
+	var charsetServer, collationServer, charsetDBVar, collationDBVar, charsetConn, collationConn string
+	row := db.Raw("SELECT @@character_set_server, @@collation_server, @@character_set_database, @@collation_database, @@character_set_connection, @@collation_connection").Row()
+	if err := row.Scan(&charsetServer, &collationServer, &charsetDBVar, &collationDBVar, &charsetConn, &collationConn); err != nil {
+		return fmt.Errorf("读取 MySQL 字符集变量失败 / Failed to read MySQL charset variables: %v", err)
+	}
+
+	// Read current schema defaults
+	var schemaCharset, schemaCollation string
+	err := db.Raw("SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = DATABASE()").Row().Scan(&schemaCharset, &schemaCollation)
+	if err != nil {
+		return fmt.Errorf("读取当前库默认字符集/排序规则失败 / Failed to read schema default charset/collation: %v", err)
+	}
+
+	toLower := func(s string) string { return strings.ToLower(s) }
+	// Allowed charsets that can store Chinese text
+	allowedCharsets := map[string]string{
+		"utf8mb4": "utf8mb4_",
+		"utf8":    "utf8_",
+		"gbk":     "gbk_",
+		"big5":    "big5_",
+		"gb18030": "gb18030_",
+	}
+	isChineseCapable := func(cs, cl string) bool {
+		csLower := toLower(cs)
+		clLower := toLower(cl)
+		if prefix, ok := allowedCharsets[csLower]; ok {
+			// collation should correspond to the charset when available
+			if clLower == "" {
+				return true
+			}
+			return strings.HasPrefix(clLower, prefix)
+		}
+		return false
+	}
+
+	// We strictly require the CONNECTION and SCHEMA defaults to be Chinese-capable.
+	// We also check database/server variables and include them in the error for visibility.
+	if !isChineseCapable(charsetConn, collationConn) || !isChineseCapable(schemaCharset, schemaCollation) || !isChineseCapable(charsetDBVar, collationDBVar) {
+		return fmt.Errorf("MySQL 字符集/排序规则必须支持中文(允许 utf8mb4/utf8/gbk/big5/gb18030),请调整服务器、数据库或连接设置。/ MySQL charset/collation must be Chinese-capable (one of utf8mb4/utf8/gbk/big5/gb18030). Details: server(%s/%s), database_var(%s/%s), connection(%s/%s), schema(%s/%s)",
+			charsetServer, collationServer, charsetDBVar, collationDBVar, charsetConn, collationConn, schemaCharset, schemaCollation)
+	}
+	return nil
+}
+
 var (
 	lastPingTime time.Time
 	pingMutex    sync.Mutex