背景描述
观前提示:本篇不是什么高大上的技术分享,只是一篇刷数据踩坑总结
笔者要执行一批刷数据的操作,需要从MySQL数据库中读出部分数据,然后进行一些加工处理,最后生成.sql的update语句文件,给db执行。
踩坑
第一步的查询操作并行化
笔者使用的DB是根据userid进行了32分库,一开始出于实现简单的角度考量,使用了简单的单进程单线程顺序查询32分库的数据,但是数据量太大,执行第一步查询的耗时超过了预期,必须要32分库并发查询。
解决办法:
- 启动32个子进程并发去查询每个分库的结果
- 通过hive命令执行map-reduce任务查询HDFS冷备份的数据
这里查询的32个分库并不是指的用户日常读写分离的主从库,而是为了给开发人员查询数据而提供的一份从库,该从库不会给线上环境的用户使用,因此慢查询也不会影响线上业务的使用。除此以外,这32个分库每天在凌晨1点执行sqoop任务将全量mysql数据转储到HDFS上作为hive表使用。整体的数据库拓扑逻辑如下:
数据加工生成的sql语句注意特殊符号
sql文件按照预期正常生成了,但是在执行过程中发生了错误,部分语句无法正常执行,笔者生成的sql语句大概形如
update tb set lastname='xxx' where userid=123 and pkid=555 and fullname='yyyxxx';
经过排查,发现失败的原因是部分update语句中生成的字符串含有特殊符号,例如包含'
、\
、 不可见字符导致显示为?
的情况,会导致mysql语句解析错误执行失败。
解决办法:
对这些特殊字符进行转义,对于筛选条件中可能出现的不可见字符显示为问号的情况,将='xxx???'
改为like 'xxx___'
,对于设置条件中可能出现不可见字符的情况报错(不过这种情况我们确实无能为力,只能从源头排查不可见字符的业务来源了,所幸笔者并没有碰到这种情况)
最后语句如下:
update tb set lastname='xxx' where userid=123 and pkid=555 and full name like 'yyyxxx';
特殊字符 | 转义方式 |
---|---|
' |
\' |
= 'xxx?' |
like 'xxx_' |
\ |
\\ |
在sql语句中每隔1000条sleep 1s防止主从延迟
这条不是笔者踩的坑,不过后续刷数据也应该要注意,因为刷数据操作的频率过快可能会导致binlog数量突增,大量刷数据的binlog占据了主从同步的队列,导致真正用户自己的操作也被延迟,由于读写分离的架构导致了写完后读不到最新结果,会十分影响业务。
一般是采用每1000条udpate语句中间执行一句select sleep(1);