如何处理Amazon DMS中MySQL/MariaDB TIME列的乱码问题
修复Amazon DMS复制MariaDB TIME列乱码问题
问题分析
你的问题根源是DMS对MariaDB启用mysql56_temporal_format后的TIME列二进制日志解析错误。MariaDB 10.1+开启该参数后,TIME列采用和MySQL 5.6一致的4字节存储格式(替代旧的3字节),但DMS的binlog读取逻辑未正确适配这种格式,导致数值被错误解析为异常时间字符串。
转换原理
正确的4字节TIME存储规则是将时间转换为秒数后,以小端字节序存储为32位有符号整数:
- 标准TIME范围:
-838:59:59到838:59:59,对应秒数范围-3020399到3020399 - DMS错误解析时,相当于把4字节二进制数据按错误规则转成了时间字符串,我们需要反向操作:将错误时间转成总秒数,修正32位有符号整数溢出,再还原为标准TIME格式。
Python 转换实现
def fix_dms_time(wrong_time_str): # 处理负号标记 is_negative = wrong_time_str.startswith('-') time_part = wrong_time_str[1:] if is_negative else wrong_time_str # 拆分时分秒,跳过无法解析的异常值 try: h, m, s = map(int, time_part.split(':')) except ValueError: return None # 计算原始总秒数(保留符号) total_seconds = (h * 3600 + m * 60 + s) * (-1 if is_negative else 1) # 修正32位有符号整数溢出 max_32bit = 2**31 - 1 min_32bit = -2**31 total_seconds = (total_seconds - min_32bit) % (max_32bit - min_32bit + 1) + min_32bit # 转换回标准TIME格式 abs_seconds = abs(total_seconds) hours = abs_seconds // 3600 remaining = abs_seconds % 3600 minutes = remaining // 60 seconds = remaining % 60 sign = '-' if total_seconds < 0 else '' return f"{sign}{hours:02d}:{minutes:02d}:{seconds:02d}" # 测试示例 print(fix_dms_time("112:16:02")) # 输出: 13:22:31 print(fix_dms_time("-911:43:62")) # 输出: 13:23:59
JavaScript 转换实现
function fixDmsTime(wrongTimeStr) { const isNegative = wrongTimeStr.startsWith('-'); const timePart = isNegative ? wrongTimeStr.slice(1) : wrongTimeStr; const parts = timePart.split(':'); if (parts.length !== 3) return null; const [h, m, s] = parts.map(Number); if (isNaN(h) || isNaN(m) || isNaN(s)) return null; let totalSeconds = (h * 3600 + m * 60 + s) * (isNegative ? -1 : 1); // 修正32位有符号整数溢出 const max32Bit = 2**31 - 1; const min32Bit = -2**31; totalSeconds = ((totalSeconds - min32Bit) % (max32Bit - min32Bit + 1)) + min32Bit; const absSeconds = Math.abs(totalSeconds); const hours = Math.floor(absSeconds / 3600); const remaining = absSeconds % 3600; const minutes = Math.floor(remaining / 60); const seconds = remaining % 60; const sign = totalSeconds < 0 ? '-' : ''; return `${sign}${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; } // 测试示例 console.log(fixDmsTime("112:16:02")); // 输出: "13:22:31" console.log(fixDmsTime("-911:43:62")); // 输出: "13:23:59"
额外建议
- 优先尝试升级AWS DMS Serverless版本,AWS后续版本大概率修复了该格式解析bug
- 若无法升级,可在Kinesis消费端嵌入上述转换逻辑,对所有TIME字段批量修正
- 验证时需对比源库与Kinesis中的TIME值,确保转换逻辑覆盖所有异常场景
内容的提问来源于stack exchange,提问作者Marco Roy
相关产品推荐
相关产品推荐

