fix: 统一数据库表排序规则

This commit is contained in:
2026-08-06 10:28:10 +08:00
parent 33848f4758
commit a2f729d274
6 changed files with 50 additions and 7 deletions
+4 -1
View File
@@ -445,7 +445,10 @@ class DatabaseManager:
mysql_type = self.TYPE_MAPPING.get(col_type, 'VARCHAR(255)') mysql_type = self.TYPE_MAPPING.get(col_type, 'VARCHAR(255)')
column_defs.append(f'`{col}` {mysql_type}') column_defs.append(f'`{col}` {mysql_type}')
sql = f"CREATE TABLE IF NOT EXISTS `{table_name}` ({', '.join(column_defs)}) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4" sql = (
f"CREATE TABLE IF NOT EXISTS `{table_name}` ({', '.join(column_defs)}) "
"ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
)
with self.get_connection() as conn: with self.get_connection() as conn:
with conn.cursor() as cursor: with conn.cursor() as cursor:
+36 -3
View File
@@ -396,7 +396,7 @@ class CellDataProcessor:
`功率` varchar(100) DEFAULT NULL, `功率` varchar(100) DEFAULT NULL,
`网络` varchar(20) DEFAULT NULL, `网络` varchar(20) DEFAULT NULL,
KEY `CGI` (`CGI`) KEY `CGI` (`CGI`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
""" """
) )
@@ -548,9 +548,17 @@ def copy_celldata_tables_to_capacity(app_config: AppConfig, logger=None) -> int:
logger.info("CellData 数据库中没有表,跳过复制") logger.info("CellData 数据库中没有表,跳过复制")
return 0 return 0
target_charset, target_collation = _database_charset_and_collation(cap_conn)
copied = 0 copied = 0
for table in tables: for table in tables:
rows = _copy_one_table(cd_conn, cap_conn, table, logger) rows = _copy_one_table(
cd_conn,
cap_conn,
table,
target_charset,
target_collation,
logger,
)
if rows >= 0: if rows >= 0:
copied += 1 copied += 1
cap_conn.commit() cap_conn.commit()
@@ -571,7 +579,28 @@ def _list_tables(conn) -> list[str]:
return [list(row.values())[0] for row in cur.fetchall()] return [list(row.values())[0] for row in cur.fetchall()]
def _copy_one_table(src_conn, dst_conn, table: str, logger=None) -> int: def _database_charset_and_collation(conn) -> tuple[str, str]:
with conn.cursor() as cur:
cur.execute(
"SELECT @@character_set_database AS `charset_name`, "
"@@collation_database AS `collation_name`"
)
row = cur.fetchone()
charset = str(row["charset_name"])
collation = str(row["collation_name"])
if not re.fullmatch(r"[A-Za-z0-9_]+", charset) or not re.fullmatch(r"[A-Za-z0-9_]+", collation):
raise RuntimeError("目标数据库字符集或排序规则名称无效")
return charset, collation
def _copy_one_table(
src_conn,
dst_conn,
table: str,
target_charset: str,
target_collation: str,
logger=None,
) -> int:
with src_conn.cursor() as cur: with src_conn.cursor() as cur:
cur.execute(f"SHOW CREATE TABLE `{table}`") cur.execute(f"SHOW CREATE TABLE `{table}`")
row = cur.fetchone() row = cur.fetchone()
@@ -584,6 +613,10 @@ def _copy_one_table(src_conn, dst_conn, table: str, logger=None) -> int:
with dst_conn.cursor() as cur: with dst_conn.cursor() as cur:
cur.execute(f"DROP TABLE IF EXISTS `{table}`") cur.execute(f"DROP TABLE IF EXISTS `{table}`")
cur.execute(create_sql) cur.execute(create_sql)
cur.execute(
f"ALTER TABLE `{table}` CONVERT TO CHARACTER SET {target_charset} "
f"COLLATE {target_collation}"
)
if count == 0: if count == 0:
if logger: if logger:
+1 -1
View File
@@ -14,4 +14,4 @@ CREATE TABLE IF NOT EXISTS `cellinfo` (
`功率` varchar(100) DEFAULT NULL, `功率` varchar(100) DEFAULT NULL,
`网络` varchar(20) DEFAULT NULL, `网络` varchar(20) DEFAULT NULL,
KEY `CGI` (`CGI`) KEY `CGI` (`CGI`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+1 -1
View File
@@ -11,4 +11,4 @@ CREATE TABLE IF NOT EXISTS `sector` (
`站型` varchar(50) DEFAULT NULL, `站型` varchar(50) DEFAULT NULL,
`网络` varchar(20) DEFAULT NULL, `网络` varchar(20) DEFAULT NULL,
KEY `CGI` (`CGI`) KEY `CGI` (`CGI`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+1 -1
View File
@@ -9,7 +9,7 @@ CREATE TABLE IF NOT EXISTS `sector_band_ref` (
`PLMN` varchar(16) DEFAULT NULL, `PLMN` varchar(16) DEFAULT NULL,
`制式` varchar(20) DEFAULT NULL, `制式` varchar(20) DEFAULT NULL,
`频段` varchar(20) DEFAULT NULL `频段` varchar(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `sector_band_ref` (`网络`,`频点下限`,`频点上限`,`PLMN`,`制式`,`频段`) VALUES INSERT INTO `sector_band_ref` (`网络`,`频点下限`,`频点上限`,`PLMN`,`制式`,`频段`) VALUES
('5G',4000,99999,NULL,'4.9G','4.9G'), ('5G',4000,99999,NULL,'4.9G','4.9G'),
+7
View File
@@ -1112,3 +1112,10 @@ CellData 处理日志细化(`app/services/cell_data.py`):
- 全脚本审计覆盖 32 个表标识:配置输入、脚本内建表和线上实际表之间无剩余大小写错配/冲突,且按 157 条语句执行顺序检查无“表尚未创建便引用”和未加反引号的表名。 - 全脚本审计覆盖 32 个表标识:配置输入、脚本内建表和线上实际表之间无剩余大小写错配/冲突,且按 157 条语句执行顺序检查无“表尚未创建便引用”和未加反引号的表名。
- 修复镜像 `capacityrepost-web:c054b48` 已部署并重启 Web;MySQL 和旧实例未重启。线上以同一数据库执行第 126、127 条核心查询通过,移动/广电临时校验结果分别为 23,227/23,107 行,临时表已删除。 - 修复镜像 `capacityrepost-web:c054b48` 已部署并重启 Web;MySQL 和旧实例未重启。线上以同一数据库执行第 126、127 条核心查询通过,移动/广电临时校验结果分别为 23,227/23,107 行,临时表已删除。
- 自动调度保持启用,正式任务 `20260806_170846` 已启动;因完整处理耗时较长,后续结果由用户自行观察。 - 自动调度保持启用,正式任务 `20260806_170846` 已启动;因完整处理耗时较长,后续结果由用户自行观察。
## 2026-08-06:统一 CellData 与容量库排序规则
- 第 136 条 SQL 的 1267 错误来自跨表 CGI 关联:容量结果表使用 `utf8mb4_unicode_ci`,CellData 复制来的 `sector/cellinfo` 保留源表 `utf8mb4_0900_ai_ci`;第 136-139 条四个 CGI/NCGI 关联均有同类风险。
- `copy_celldata_tables_to_capacity` 在目标空表创建后、插入前读取目标数据库的 `@@character_set_database/@@collation_database` 并执行 `ALTER TABLE ... CONVERT`,复制表不再继承不兼容的源排序规则;字符集和排序规则名称限定为字母数字下划线。
- `CellDataProcessor`、`DatabaseManager` 和三份 `db_init` 建表 SQL 均显式使用 `utf8mb4_unicode_ci`,避免 MySQL 8 在只写 `DEFAULT CHARSET=utf8mb4` 时回落到 `utf8mb4_0900_ai_ci`。
- 线上 `celldata` 与 `CapacityReport` 两库的 `sector/cellinfo` 已迁移为 `utf8mb4_unicode_ci`;4G/5G 结果表分别关联 sector/cellinfo 的四组真实查询均通过。自动重试任务 `20260806_180436` 保持运行,未重启容器。