【MySQL】备份数据库并验证数据库的条数是否正确

1,120 阅读5分钟

前言:

需要对生产环境的数据进行更新和迁移,因此操作前需要做一次数据的备份,但是备份的数据如何确保数量正确,因此有了下文。虽然有阿里云的全盘备份,但是这是在有钞能力的情况下才能使用,正常小项目不可能这样去做,因此手动的导出是我能想到性价比最高的方式了 兄弟们有更好的方式可以提点提点小弟,谢谢


网上最常见的几种备份方式:

单表备份还原

  • 优点:操作简单,并且能比较直观的看到备份的结果,甚至可以通过SQL语句去校验是不是两个表的数据完全一致。
  • 缺点:表比较少的时候确实很好用,但是一旦涉及到的备份表很多的时候,问题就比较明显了,每张表都要写一条语句,其次是如果数据量巨大,这样的操作效率极低,并且在磁盘空间不允许的情况下,甚至可能把数据库给挤爆(同事提醒我的,本来我也没想到),毕竟这就是直接牺牲数据库容量去进行备份的,一旦数据库崩了,不但没起到备份作用,甚至还把原有的数据给弄没了。
-- 单表备份
CREATE TABLE xxxxx_bak_1209 AS SELECT * FROM xxxxx;
-- 单表还原
RENAME TABLE xxxxx_bak_1209 TO xxxxx;

全库备份(指令版)

  • 优点:安全!安全!安全!能完全的将数据库恢复到数据变更之前的状态和数据。不论是否用得上全库还原,都应该在较大变动操作之前进行一次全库备份的操作,毕竟这是数据安全最保险的
  • 缺点:如果在备份和还原的过程中忘记某些服务未关闭很可能在备份和还原的时间间隔之内产生的数据丢失,因此使用这种方式之前请确保所有的服务均已停下。同时数据库比较大的时候也可能出现备份和还原时间比较旧的问题(毕竟生产环境时间就是金钱)
-- 数据库全量备份
mysqldump -h127.0.0.1:3306 -uroot -ppassword DB_name> xxxx_bak_1208.sql;
-- 全量还原
mysql -h127.0.0.1:3306 -uroot -ppassword DB_name< xxxx_bak_1208.sql;

全库备份(工具导出)

  • 优点:跟上面一样,区别在于有一个图像界面去操作,对于没有较好的代码基础的操作人员来说相对友好一些。
  • 缺点:备份的配置如果不太清楚,可能导致数据的丢失,因为有些工具导出有一个设置叫做“报错跳过”,因此很可能会导致缺失了,都很难发现
-- Navicate
数据名称  ->  右键  ->  转储SQL文件 -> 结构和数据 ->  确定保存的位置和名称 -> 确定
-- 其他工具
.....


备份完如何确定SQL文件确实可靠?

我采用的就是最蠢但是也最能说服自己的方法,创建一个新的库把数据导入,然后校验数据库数据量一共有多少,与原数据库进行比较,只要数量是一样的,基本上就没有太大的问题。 正是有了这样的想法,才有接下来发现的问题,如何统计一个数据库究竟有多少数据?有人说

select count(*);

这么做确实没毛病,但是如果有几十张表,一个个的count,但凡有一个统计结果记错了,那你重来呢?还是判定备份的SQL有问题呢?所以这个方法只能说适用于表少的时候。

然后翻了许久技术论坛看到了MySQL本身是对数据库有统计数据的,欣喜若狂的去尝试了一下

1.参数:

     databaseName:数据库名

     classTableName :一类表的名称

2.SQL语句:

SELECT
    t.TABLE_NAME,
    t.TABLE_ROWS,
    t.TABLE_COMMENT 
FROM
    information_schema.`TABLES` t 
WHERE
    t.TABLE_SCHEMA = 'databaseName' 
    AND t.TABLE_NAME LIKE 'classTableName' 
ORDER BY
    t.TABLE_ROWS DESC

结果为三个字段  

    TABLE_NAME:表名称

    TABLE_ROWS :表数据量

    ABLE_COMMENT :表的注释

结果类似这样,你以为这样就完事了? 在这里插入图片描述 我对比原库和还原库发现,不好意思,数量对不上!!!那一刹那我想到的就是

mysqldump不靠谱!!! mysqldump不靠谱!!! mysqldump不靠谱!!!

官方的插件居然连导出的数据都有问题?

那一刻我甚至怀疑备份是否真的有效,难道只能钞能力去用阿里云的磁盘备份了? 其实不然,问题在哪? 问题出在了统计的结果是有误的! 问题出在了统计的结果是有误的! 问题出在了统计的结果是有误的! 无意中查询资料发现,原来这种统计的方式是要看数据库引擎类型的,具体的我不多说,主要的原有就是这个统计会因为数据库的引擎类型,而有时间差,就是说这个统计结果不是实时同步的,所以在某些情况下可信,某些情况下它又不可信了。

那怎么办?

解法如下:

-- 执行的结果复制出来,删掉最后一个UNION ALL就是所有表的数目了
SELECT CONCAT( 'SELECT "', TABLE_NAME, '", COUNT(*) FROM ', TABLE_SCHEMA, '.', TABLE_NAME, ' UNION ALL' )  EXEC_SQL
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'DB_NAME';

将导出的结果,直接复制,去掉最后一个UNION ALL,然后执行语句, 结果就是所有表的统计结果,这其实就是一个个表count数据,但是语句不需要自己写,并且还不会漏掉表,这不香吗? 对比执行的结果发现,原来数据量是一样的,所以之前的想法多疑了,但是这个问题确实引起我的注意,似乎不能过分的依赖工具带来的便利,还是需要确认真正的确认一下数据的真实性和可靠性的,不然数据丢了,说工具再可靠都没有任何意义....


希望这篇文章能够帮到你,有问题可以私信,欢迎交流!