Files
tuanwei-java/sql/20261026_timezone_8h_check.sql
weicw 9e88c53052 fix: 数据源会话时区强制 +08:00,修复创建时间早 8 小时
生产数据库容器(1Panel-mariadb-ZOpD)的 system_time_zone 是 UTC,而数据源 URL 写着

serverTimezone=Asia/Shanghai:JDBC 会话时区是 UTC、驱动却按 +08 解析服务端返回的字面量,

于是 timestamp 列(分类管理、文章、系统日志、审核流、AI 对话等)读出来整体早 8 小时。

数据源 URL 增加 connectionTimeZone=%2B08:00&forceConnectionTimeZoneToSession=true,

连接建立时把会话时区设为 +08:00,与 JVM 默认时区、spring.jackson.time-zone 保持一致。

用偏移量而非命名时区,避免 MariaDB 容器未加载时区表时报 Unknown or incorrect time zone。

附 sql/20261026_timezone_8h_check.sql:部署后的时区自检、分类管理核对,

以及 datetime 列历史 UTC 字面量与教师建号行的时间回填模板(默认注释未执行)。
2026-10-26 11:09:15 +08:00

57 lines
3.5 KiB
SQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- 时区 8 小时偏差:修复后核对 + 历史数据排查(默认只读,改数据的语句都已注释)
-- 背景:生产 DB 容器 1Panel-mariadb-ZOpD 系统时区是 UTC,应用容器/JVM 是 +08,
-- 驱动参数 serverTimezone=Asia/Shanghai ⇒ 会话时区(UTC) 与驱动连接时区(+08) 不一致。
-- 修复:application-prod.yml 的 url 加 connectionTimeZone=%2B08:00&forceConnectionTimeZoneToSession=true,
-- 连接建立时把会话时区设为 +08:00,与驱动一致。
-- 预期:
-- * timestamp 列(cms_* / ai_chat_* / sys_* / gxmu_review_* / shop_user_oauth)存的是真实时刻(epoch),
-- 修复后读出来自动回正:「知识库管理-分类管理」的创建时间会从 09:11 变成 17:11(真实时间)。
-- * datetime 列(gxmu_* 业务表)如果创建时间来自列默认值 CURRENT_TIMESTAMP,存的是 UTC 字面量,
-- 修复后仍然早 8 小时,需要按表核对后回填。
-- * 代码里用 java.util.Date 显式写 timestamp 列的行(TeacherAccountService 教师建号/授权/冻结),
-- 存的是 epoch 偏晚 8 小时,修复后会显示晚 8 小时,需要 -8h 回填。
-- 1) 会话时区自检(部署后执行,session 应为 +08:00 或 Asia/Shanghai)
SELECT @@global.time_zone AS global_tz, @@session.time_zone AS session_tz,
@@system_time_zone AS system_tz, NOW() AS db_now, UTC_TIMESTAMP() AS db_utc;
-- 2) 分类管理核对(修复后 create_time 应比修复前 +8 小时)
SELECT category_id, title, create_time, update_time
FROM cms_article_category ORDER BY category_id;
-- 3) 教师账号(TeacherAccountService 用 new Date() 显式写入)—— 修复后可能晚 8 小时
SELECT COUNT(*) AS teacher_user_cnt FROM sys_user WHERE user_code IS NOT NULL;
SELECT user_id, user_code, username, real_name, create_time, update_time
FROM sys_user WHERE user_code IS NOT NULL ORDER BY create_time DESC LIMIT 30;
-- 4) gxmu_* datetime 表排查:重点看 HOUR(create_time) < 8 的行(北京时间凌晨不可能大量建数据)
-- 逐表替换表名继续:gxmu_declare / gxmu_student / gxmu_teacher / gxmu_sync_record /
-- tzb_project_list / tzb_talent_list / wxxzx_* / qmgc_form / sjqn / ...
SELECT 'gxmu_declare' AS tbl, COUNT(*) AS total,
MIN(create_time) AS min_ct, MAX(create_time) AS max_ct,
SUM(HOUR(create_time) < 8) AS early_hour_rows
FROM gxmu_declare;
-- 5) 【谨慎】教师建号行 -8h 回填模板:先跑第 3 步确认数量与样本,备份后再执行
-- START TRANSACTION;
-- UPDATE sys_user
-- SET create_time = create_time - INTERVAL 8 HOUR,
-- update_time = update_time - INTERVAL 8 HOUR
-- WHERE user_code IS NOT NULL
-- AND create_time >= '<教师账号同步功能上线时间>';
-- UPDATE sys_user_role ur JOIN sys_user u ON u.user_id = ur.user_id
-- SET ur.create_time = ur.create_time - INTERVAL 8 HOUR,
-- ur.update_time = ur.update_time - INTERVAL 8 HOUR
-- WHERE u.user_code IS NOT NULL
-- AND ur.create_time >= '<教师账号同步功能上线时间>';
-- COMMIT;
-- 6) 【谨慎】gxmu_* datetime 列 +8h 回填模板:必须先按表确认这些行是列默认值写的 UTC 字面量。
-- 代码里 LocalDateTime.now() 写入的行在 JVM=+08 时已经是正确北京时间,回填会多 8 小时。
-- START TRANSACTION;
-- UPDATE gxmu_xxx
-- SET create_time = create_time + INTERVAL 8 HOUR,
-- update_time = update_time + INTERVAL 8 HOUR
-- WHERE create_time < '<切换时间点>';
-- COMMIT;