• 微信
    咨询
    微信在线咨询 服务时间:9:00-18:00
    纵横数据官方微信 使用微信扫一扫
    马上在线沟通
  • 业务
    咨询

    QQ在线咨询 服务时间:9:00-18:00

    选择下列产品马上在线沟通

    纵横售前-老古
    QQ:519082853 售前电话:18950029581
    纵横售前-江夏
    QQ:576791973 售前电话:19906048602
    纵横售前-小李
    QQ:3494196421 售前电话:19906048601
    纵横售前-小智
    QQ:2732502176 售前电话:17750597339
    纵横售前-燕子
    QQ:609863413 售前电话:17750597993
    纵横值班售后
    QQ:407474592 售后电话:18950029502
    纵横财务
    QQ:568149701 售后电话:18965139141

    售前咨询热线:

    400-188-6560

    业务姚经理:18950029581

  • 关注

    关于纵横数据 更多优惠活动等您来拿!
    纵横数据官方微信 扫一扫关注官方微信
  • 关闭
  • 顶部
  • 您所在的位置 : 首页 > 新闻公告 > 云主机异常数据处理方法?

    云主机异常数据处理方法?

    数据这东西,平时安安静静躺在云盘里的时候,你几乎感觉不到它的存在。可一旦出了问题,那种心慌的感觉,做过程序员和运维的人都懂。我到现在都记得第一次遇到数据异常的场景:一台云主机上的MySQL数据库,运行得好好的,突然某几张表查询不出来了,报错提示“Table crashed”。当时的我手足无措,整整熬了一个通宵才把数据捞回来。后来随着经验增长,我慢慢总结出了一套针对云主机上异常数据的处理方法。今天借着这个机会,跟你好好聊聊这个话题。

    什么是异常数据,它和硬件故障有什么不同

    在聊处理方法之前,我们得先弄清楚什么叫做“异常数据”。它跟服务器宕机、网络不通这类故障不一样。服务中断的时候,你能明显感觉到系统不可用。但数据异常往往很隐蔽,系统还可能照常运行,只是你某天突然发现订单金额少了一位数字,或者用户头像变成了别人的照片,再或者有一个目录里出现了大量乱码文件。

    异常数据的范围很广,主要包括:数据损坏比如数据库表文件被破坏,文件内容变成了乱码。数据不一致比如主从复制出现了偏差,关联表之间的外键对不上。数据被误删或者覆盖比如手抖执行了rm或者drop命令。数据被恶意篡改比如中了勒索病毒或者被入侵后植入了后门。以及数据出现大量脏数据,比如程序bug写入了重复的、格式错误的数据。

    我曾经处理过一个让人印象深刻的异常数据案例:一家电商公司的订单系统,运营人员在后台导出订单报表的时候,发现近三天的订单金额总计居然是负数。排查下来,是因为某个促销活动的代码在处理退款逻辑时,没有判断订单状态,导致一个订单同一个商品被重复退款了三次。金额产生了负值,但数据库里的订单行本身并没有损坏,而是数据的内容错了。这种异常数据最难发现,因为它不会触发任何系统报警,只有业务人员在使用的时候才会觉得“不对劲”。

    第一步:立即止损,防止异常扩散

    当你发现云主机上出现了异常数据,第一反应不应该是急着去恢复或者修复,而是先“止损”。什么意思呢就是说要尽快切断异常数据的源头,防止它继续蔓延或者覆盖更多正常数据。

    讲一个真实的教训。有一家公司的云主机中了勒索病毒,病毒把大量文档和数据库文件加密了,留下一个勒索信。当时负责的同事第一反应是去杀毒、去解密,结果在折腾的过程中,病毒还在后台继续扫描和加密新产生的文件。原本只有几百个文件被加密,等到真正开始恢复的时候,已经变成了几千个。正确的做法是,发现异常数据的第一时间,就把这台云主机从网络中隔离出来。最简单粗暴的方法是临时关闭它的公网和内网网卡,或者直接在云控制台的安全组里把所有入站和出站流量都拒绝。如果是勒索病毒,还要立刻修改所有可能泄露的密码和密钥。

    另一个需要止损的场景是:你发现某个定时任务或者数据处理脚本产生了错误的数据。比如一个数据同步脚本,因为源数据格式变了,开始往目标数据库里写入大量乱码。这时候你应该立刻停掉这个脚本,防止它继续写入更多的异常数据。有时候,你甚至需要临时锁住某些表或者禁用某些接口,等排查清楚之后再恢复。

    第二步:判断异常的范围和类型

    止损之后,你需要尽快弄清楚三个问题:第一,哪些数据出了问题第二,问题的根源是什么第三,有没有影响到备份或者副本。

    我处理过一次MySQL数据库的异常,现象是某几张InnoDB表在执行查询的时候总是报“corrupted”。我用CHECK TABLE命令看了一下,确实提示损坏。但是我没有急着去修复,而是先看这几张表在其他从库上的状态。结果发现,主库的表损坏了,但从库上的同样表是完好的。这说明问题不是逻辑层面的错误,而是主库所在的这块云盘或者文件系统出了物理性问题。于是我立刻把业务切换到从库上,把从库提升为主库,避免了停机时间。然后才在主库上用innodb_force_recovery参数启动数据库,把数据导出来。

    还有一次,客户怀疑他们的对象存储里的图片有一部分被“污染”了,显示出来有花屏或者颜色失真。我们用脚本抽查了不同时间段上传的图片,发现只有最近两天上传的有问题,而更早的图片是正常的。这就有力地缩小了排查范围,说明问题可能出在最近两天的上传程序或者网络传输环节上。最后定位到是图像处理库的一个新版本有bug,导致了图片编码错误。

    判断异常数据范围的时候,我习惯按照时间维度、路径维度、类型维度来分别取样。时间维度就是看看异常数据集中在哪个时间段产生的。路径维度就是看看是不是都在同一个目录、同一张表、同一个桶里。类型维度就是看看是不是只有某种格式或者某种来源的数据出问题了。这三个维度交叉定位,往往能很快找出规律。

    数据损坏的修复方法

    数据损坏通常意味着存储介质上保存的信息跟原来的内容不一致了。在云主机环境下,常见的原因包括云盘底层出现坏块、文件系统元数据损坏、数据库的页校验失败,以及突然断电或强制重启导致的写入未完成。

    我处理过最典型的一个文件系统损坏案例。一台云主机在强制断电重启之后,某个挂载点变成了只读状态,而且ls列目录的时候一直报“Input/output error”。用dmesg看了下,大量“EXT4-fs error”的记录。我判断是文件系统元数据损坏了。解决办法是先用umount卸载这个分区,然后执行fsck检查修复。由于是云盘,我担心修复过程中可能把数据弄丢,所以先在云控制台给这块云盘做了一个快照。有了快照保底之后,我再执行fsck -y /dev/vdb1,系统自动修复了多处不一致的inode和块引用。修复完成之后重新挂载,所有文件都恢复了正常。如果没有提前做快照,万一修复失败,数据就真的丢了。

    对于数据库层面的数据损坏,MySQL的InnoDB引擎通常有一定的自愈能力。你可以在配置文件里设置innodb_force_recovery从1到6的不同级别,让数据库跳过一些校验步骤强制启动。级别越高跳过的越多,但风险也越大,可能会丢失数据或者产生不一致。我个人的建议是,先从低级别开始尝试,能启动之后马上用mysqldump把数据导出到另一个正常的数据库里。宁愿丢一点点最近的事务,也不要冒着整个库打不开的风险去用高级别恢复。

    另一种数据损坏是文件内容变成了乱码,但文件大小看起来正常。这种情况很可能是写入过程中发生了错误,或者被某些程序错误地覆盖了。如果你有之前的备份,直接从备份里恢复就好了。如果没有备份,可以试试从云平台的快照里找找看。云主机的系统盘和数据盘一般都支持定期快照,你可以回滚到几个小时甚至几天前的快照来恢复数据。但要注意,快照回滚会丢失快照创建之后的所有变更,这是一个“一锤子买卖”,操作之前一定要权衡清楚。

    误删除数据的恢复方法

    误删除恐怕是所有数据异常里最让人心痛的。一个rm -rf,一个drop database,或者一个unlink,几秒钟的操作可能毁掉几个月的心血。好消息是,在云主机环境下,误删除不一定意味着数据彻底消失。

    我有一个做设计的客户,有一天他登录云主机清理文件,本来只想删除一个临时文件夹,结果在终端里敲命令的时候,路径不小心写错了,rm -rf * 在一个重要的项目目录里执行了。等他回过神的时候,几十个设计源文件已经没了。我第一时间让他停止对这块磁盘的任何写入操作,因为Linux下的rm只是删除文件的硬链接,文件内容还留在磁盘上,只是标记为“已释放”。只要没有新的写入覆盖掉这些磁盘块,就有希望恢复。

    我们用了一款叫extundelete的工具,专门针对ext3和ext4文件系统进行恢复。指定被删除文件所在的分区和丢失文件的路径,工具扫描了一段时间,找出了最近被删除的几百个文件。客户从中找到了绝大部分源文件,只有几个最近创建的大文件因为磁盘块已经被部分覆盖而恢复得不完整。从那以后,他的云主机上多了一个每天自动运行的备份脚本,而且重要的文件都会存一份到云存储的对象桶里。

    对于数据库的误删除,比如不小心执行了DROP TABLE或者DELETE忘了加WHERE条件,恢复起来需要依靠数据库的备份和binlog。MySQL的binlog记录了所有数据变更操作,如果你开启了binlog,就可以通过mysqlbinlog工具把误操作之前的SQL提取出来,然后进行“反向回放”。比如误执行的是一条DELETE,你就从binlog里找到对应的INSERT语句,重新插入回去。这个方法需要一定的技术水平,而且要求你的binlog没有被清理掉。所以平时开启binlog,并且定期备份到其他机器上,是防御误删除的重要手段。

    还有一个更简单的办法:很多云服务商提供了“数据库回档”功能,可以把某个数据库或者某张表回滚到过去任意一个时间点,前提是你开启了日志备份。这个功能我测试过,真的是误操作的“后悔药”。有一次我在测试环境里误删了一个生产库的配置表,慌了十分钟,然后想起云控制台有“根据备份集恢复”的选项,点了几下就把表恢复了,前后不到五分钟。

    数据不一致的处理

    数据不一致比损坏和误删除更难处理,因为它不报错,数据也能查询,但数值对不上。常见于主从复制的场景,或者分布式系统里不同节点之间的数据没有达成一致。

    我遇到过一台云主机上主从复制的数据不一致问题。业务人员反映,在后台看到的订单统计数据,和从前台页面看到的不一致。检查发现,前台的查询走的是从库,后台走的是主库。两个库的数据对不上。进一步查看,从库的复制进程报“Slave SQL: Could not execute Write_rows event on table”,原来是因为主库和从库的表结构在某次变更中出现了差异。那次变更只应用到了主库,从库忘了执行,导致后续相关的更新操作在从库上全部失败,数据从此开始分裂。

    解决的方法是,先让从库停止复制,然后重新做一次数据同步。具体做法是把主库的数据导出并导入到从库,再启动复制。这个过程比较耗时,而且要求停机或者至少加只读锁。为了减少影响,我们选择了业务低谷期的凌晨进行操作,还提前用pt-table-checksum工具检测了其他表是否也存在一致性问题。

    另一种数据不一致是应用层产生的。比如说,一个用户注册时,用户表里插入了记录,但积分表里忘了插入初始积分。这种问题需要写专门的修复脚本,扫描那些“孤儿”记录,然后补上缺失的数据。在写这种脚本之前,一定要先搞清楚业务规则,并且在测试环境里跑一遍,确认不会产生新的异常。

    恶意篡改和勒索病毒的应对

    云主机数据被恶意篡改是让人最愤怒也最无力的情况。我曾经帮一个做外贸的企业处理过勒索病毒:他们的一台云主机上所有文档、图片、数据库文件都被加密成了后缀为crypt的文件,每个目录里都多了一个README文本,要求支付比特币解密。客户当场就懵了,因为那台主机上存着过去三年的客户合同和产品图纸,而且没有做任何异地备份。

    处理这种事情,第一步永远是不给赎金。给了赎金也不一定能拿回数据,而且会助长犯罪分子的气焰。第二步,立即将这台云主机的网络断开,防止病毒进一步扩散到同一VPC下的其他主机。第三步,看看云控制台里有没有快照或者备份。幸运的是,这家企业的另一名运维人员虽然没有做异地备份,但云平台默认开启了每周一次的系统盘快照,最近的一次快照是在病毒加密前四天。我们通过快照回滚,把整个系统盘恢复到四天前的状态,丢失了四天的数据,但保住了绝大部分重要资料。如果连快照都没有,那只能认栽了。

    对于恶意篡改,预防远比恢复重要。具体做法包括:定期异地备份关键数据,使用对象存储的生命周期管理自动归档。严格限制云主机的访问权限,不使用弱密码,关闭不必要的端口。安装云安全产品,比如主机安全、文件完整性监控等。对于数据库,可以开启操作日志审计,一旦发现异常变更,能够追踪到源头。

    脏数据和重复数据的清洗

    除了严重的损坏和丢失,还有一种常见异常是“脏数据”。业务系统跑久了,难免会出现各种各样不规范的数据。比如用户昵称里出现了emoji表情没处理好变成了问号,时间字段存了“2022-13-01”这种非法日期,或者因为代码bug产生了大量重复的订单记录。

    处理脏数据,最好的方法不是用手工一条条改,而是写清洗脚本。我参与过一个大促后的数据清洗工作,因为秒杀系统的逻辑缺陷,同一个用户对同一个商品生成了十几条重复的订单记录,状态还都是“待支付”。运营人员统计订单数的时候,数字虚高了几十倍。我们的做法是先用SQL找出所有重复订单,然后根据“同一个用户同一个商品只保留最早的一条有效订单”的规则,删除多余的重复记录。在执行删除之前,先把要删除的订单ID导出备份,然后在一个事务里执行删除操作。一旦出了问题,可以立即回滚。

    清洗脏数据的另一个原则是:尽量不要直接修改原始数据,而是创建一个新的干净表,把清洗后的数据导进去,然后通过表切换的方式来替换。这样即使清洗脚本写错了,原始数据还在,随时可以重来。

    建立数据异常处理的应急预案

    说了这么多方法,我觉得最有价值的建议是:提前制定一份数据异常处理的预案,不要等出事了再去想怎么办。

    这份预案应该包括:第一,数据异常的发现机制,比如数据库的checksum监控、文件完整性校验、业务层面的对账脚本。第二,联系清单,列出云服务商的技术支持联系方式、内部DBA和运维的紧急联系人。第三,处理流程图,比如先止损再定位,先恢复再排查。第四,各种场景下的恢复手册,包括从备份恢复、从快照回滚、用binlog回档、用数据恢复工具等具体操作步骤。第五,定期演练。光有文档没有用,要真的在测试环境里模拟一次数据损坏或者误删除,看团队能否在规定时间内完成恢复。

    之前我们团队每隔一个季度就会组织一次“数据灾难演练”。随机选一台云主机,我自己偷偷进去删掉一些重要文件或者弄坏一张表,然后看看负责的同事需要多久能发现、多久能定位、多久能恢复。第一次演练的时候,大家手忙脚乱,花了两个多小时。到了第三次演练,全程只用了二十多分钟。这种信任感是平时用钱都买不到的。

    总结

    云主机上的异常数据处理,说到底是一场跟时间和错误的赛跑。数据损坏了,你要在备份和工具里找希望。误删除了,你要懂得停止写入并尽快恢复。数据不一致了,你要耐心排查每一步复制和事务的细节。被恶意篡改了,你要依靠快照和安全策略来救火。

    但我想说的是,最好的“处理方法”,其实是把工作做在异常发生之前。定期备份、定期快照、开启binlog、做好权限管控、部署安全防护、演练数据恢复流程,这些看似琐碎的事情,在数据安全的账本上,每一笔都是赚的。没有谁能保证自己永远不会碰到数据异常,但你可以保证在异常来临的时候,有方法、有工具、有底气去面对。数据是云主机上最宝贵的资产,而保护数据的能力,是每一个在云上工作的人最该练好的基本功。



    最新推荐


    微信公众帐号
    关注我们的微信