fix: 修复MySQL字符集问题,防止中文乱码

## 问题描述
用户反馈:菜单comment字段可能出现乱码

## 问题分析

### 乱码原因
1. **MySQL连接字符集不匹配**:
   - 客户端未指定字符集
   - 默认字符集与数据不匹配

2. **终端显示问题**:
   - 终端编码与数据库编码不一致
   - 查询结果传输过程中字符集转换错误

### 数据库状态检查
```sql
-- 当前配置
character_set_client     = utf8mb4  
character_set_connection = utf8mb4  
character_set_database   = utf8mb4  
character_set_results    = utf8mb4  

-- 表字符集
sys_menu: utf8mb4_general_ci  
```

## 解决方案

### 1. 更新import_menu.sh导入脚本
**修改**:所有mysql命令添加`--default-character-set=utf8mb4`

```bash
# 修复前 
mysql -h"$DB_HOST" -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" < "$SQL_FILE"

# 修复后 
mysql -h"$DB_HOST" -u"$DB_USER" -p"$DB_PASS" --default-character-set=utf8mb4 "$DB_NAME" < "$SQL_FILE"
```

### 2. 创建字符集修复工具
**新增**:`sql/fix_charset.sh`

**功能特性**:
-  检查数据库字符集配置
-  检查表字符集设置
-  测试查询菜单数据
-  一键修复表字符集
-  自动备份原表数据

**使用方法**:
```bash
cd sql
./fix_charset.sh
```

**修复流程**:
1. 检查当前字符集配置
2. 显示菜单数据(检测乱码)
3. 用户确认是否修复
4. 创建备份表
5. 转换表字符集为utf8mb4
6. 验证修复结果

## 预防措施

### 数据导入时
```bash
# 始终指定字符集
mysql --default-character-set=utf8mb4 -h... < file.sql
```

### 数据查询时
```bash
# 查询时指定字符集
mysql --default-character-set=utf8mb4 -h... -e "SELECT ..."
```

### 应用程序配置
```yaml
# application.yml中确保
spring:
  datasource:
    url: jdbc:mysql://...?characterEncoding=utf8mb4&useUnicode=true
```

## 验证结果
```sql
SELECT menu_id, menu_name, remark FROM sys_menu WHERE parent_id = 0;

2000  盘古管理  盘古用户平台业务菜单  
1     系统管理  系统管理目录          
2     系统监控  系统监控目录          
```

## 相关文件
- sql/import_menu.sh - 菜单导入脚本(已修复)
- sql/fix_charset.sh - 字符集修复工具(新增)

---
作者:湖北新华业务中台研发团队
This commit is contained in:
神码-方晓辉 2026-02-01 13:21:43 +08:00
parent bcb1c6e397
commit a7b997321c
2 changed files with 100 additions and 3 deletions

97
sql/fix_charset.sh Executable file
View File

@ -0,0 +1,97 @@
#!/bin/bash
# ============================================================
# 脚本名称fix_charset.sh
# 功能说明:修复数据库字符集和乱码问题
# 作 者:湖北新华业务中台研发团队
# 创建时间2026-01-31
# 使用方法:./fix_charset.sh
# ============================================================
set -e
# 数据库配置
DB_HOST="8.148.25.55"
DB_PORT="3306"
DB_USER="root"
DB_PASS="aly2024A"
DB_NAME="pguser-db"
echo "============================================================"
echo "数据库字符集检查与修复工具"
echo "============================================================"
echo ""
# 1. 检查数据库字符集
echo "1. 检查数据库字符集配置..."
mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" --default-character-set=utf8mb4 -e "
SHOW VARIABLES LIKE 'character_set%';
" 2>&1 | grep -v "Warning"
echo ""
# 2. 检查sys_menu表字符集
echo "2. 检查sys_menu表字符集..."
mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" --default-character-set=utf8mb4 "$DB_NAME" -e "
SELECT
TABLE_NAME,
TABLE_COLLATION,
COLUMN_NAME,
COLUMN_TYPE,
CHARACTER_SET_NAME,
COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = '$DB_NAME'
AND TABLE_NAME = 'sys_menu'
AND COLUMN_NAME IN ('menu_name', 'remark');
" 2>&1 | grep -v "Warning"
echo ""
# 3. 测试查询菜单数据
echo "3. 测试查询菜单数据(检查是否有乱码)..."
mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" --default-character-set=utf8mb4 "$DB_NAME" -e "
SELECT menu_id, menu_name, remark
FROM sys_menu
WHERE parent_id = 0
ORDER BY order_num;
" 2>&1 | grep -v "Warning"
echo ""
echo "4. 如果上面显示有乱码,是否修复表字符集?(y/n): "
read -p "" confirm
if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
echo ""
echo "正在修复sys_menu表字符集..."
# 备份表
echo " - 创建备份表..."
mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" --default-character-set=utf8mb4 "$DB_NAME" -e "
CREATE TABLE IF NOT EXISTS sys_menu_backup_charset AS SELECT * FROM sys_menu;
" 2>&1 | grep -v "Warning"
# 转换表字符集
echo " - 转换表字符集为utf8mb4..."
mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" --default-character-set=utf8mb4 "$DB_NAME" -e "
ALTER TABLE sys_menu CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
" 2>&1 | grep -v "Warning"
echo ""
echo "✅ 字符集修复完成!"
echo ""
echo "验证修复结果:"
mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" --default-character-set=utf8mb4 "$DB_NAME" -e "
SELECT menu_id, menu_name, remark
FROM sys_menu
WHERE parent_id = 0
ORDER BY order_num;
" 2>&1 | grep -v "Warning"
else
echo ""
echo "❌ 操作已取消"
fi
echo ""
echo "============================================================"
echo "检查完成!"
echo "============================================================"

View File

@ -42,14 +42,14 @@ fi
# 执行导入 # 执行导入
echo "" echo ""
echo "正在导入菜单数据..." echo "正在导入菜单数据..."
mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" < "$SQL_FILE" mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" --default-character-set=utf8mb4 "$DB_NAME" < "$SQL_FILE"
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
echo "" echo ""
echo "✅ 菜单数据导入成功!" echo "✅ 菜单数据导入成功!"
echo "" echo ""
echo "菜单统计:" echo "菜单统计:"
mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e " mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" --default-character-set=utf8mb4 "$DB_NAME" -e "
SELECT SELECT
CASE CASE
WHEN menu_id < 2000 THEN 'RuoYi系统菜单' WHEN menu_id < 2000 THEN 'RuoYi系统菜单'
@ -61,7 +61,7 @@ if [ $? -eq 0 ]; then
WITH ROLLUP;" WITH ROLLUP;"
echo "" echo ""
echo "顶级菜单:" echo "顶级菜单:"
mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" "$DB_NAME" -e " mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASS" --default-character-set=utf8mb4 "$DB_NAME" -e "
SELECT menu_id, menu_name, order_num, visible, status SELECT menu_id, menu_name, order_num, visible, status
FROM sys_menu FROM sys_menu
WHERE parent_id = 0 WHERE parent_id = 0