背景

有一个特殊环境需要进行人肉迁移数据,对比了表里的数据一模一样,但是无论如何checksum就是不一致,那么问题出在哪里呢?

问题排查

数据是否一致

眼睛都把屏幕盯穿了,也没发现不一致的数据。

导出数据的方式

image checksum还是不一致,所以这个原因排除。

MySQL版本

嗯,这个确实不一样,源端是5.5,目的端是5.6,但是这个是checksum函数不一样吗?还是表的结构变了?咨询了内核的同学,说checksum的源代码没变啊,接下来那应该是表结构变了?通过查手册发现:

  1. The checksum value depends on the table row format. If the row format changes, the
  2. checksum also changes. For example, the storage format for temporal types such as
  3. TIME, DATETIME, and TIMESTAMP changes in MySQL 5.6 prior to MySQL 5.6.5, so if a
  4. 5.5 table is upgraded to MySQL 5.6, the checksum value may change.

既然这样了,那我们就来验证下是不是因为datetime的问题。 image 嗯,确实是datetime的格式导致的。

总结

这个问题总结来说是因为MySQL5.5和5.6的时间存储格式有变化,导致了checksum不一样。

这个问题知道原因后觉得非常简单,但是排查起来却不是那么简单的。遇到问题不要慌,理出要查的1,2,3,然后用排除法一步一步验证就能知道问题在哪里了。

附一详细步骤如下:

源端:

1.备份结构和数据

  1. mysqldump -h127.0.0.1 -P源端口 -u root --default-character-set=utf8 -B drcdb>src_lingluo.sql

2.拷贝文件

  1. scp src_lingluo.sql lingluo.sss@目的端:/tmp

目的端:

3.把数据导进去

  1. mysql>set names utf8;source /tmp/src_lingluo.sql;

4.在两边取checksum

  1. sh get_checksum.sh

5.目的端:

  1. scp table_checksum.txt lingluo.sss@目的端:/tmp

6.vimdiff 对比文件

如果文件内容一样的话,说明数据一样

附二get_checksum.sh

  1. #!/bin/sh
  2. port=$1
  3. table_list='`mysql -h127.0.0.1 -P${port} -u root -A -N << EOF | tail -n +3
  4. use db_name;show tables
  5. EOF`'
  6. for i in ${table_list}
  7. do
  8. table_cs='`mysql -h127.0.0.1 -P${port} -u root -A -N -D db_name -e \"checksum
  9. table ${i};\"`'
  10. echo ${table_cs} >> table_checksum.txt
  11. done