背景描述
觀前提示:本篇不是什么高大上的技術(shù)分享,只是一篇刷數(shù)據(jù)踩坑總結(jié)
筆者要執(zhí)行一批刷數(shù)據(jù)的操作,需要從MySQL數(shù)據(jù)庫中讀出部分數(shù)據(jù),然后進行一些加工處理,最后生成.sql的update語句文件,給db執(zhí)行。
踩坑
第一步的查詢操作并行化
筆者使用的DB是根據(jù)userid進行了32分庫,一開始出于實現(xiàn)簡單的角度考量,使用了簡單的單進程單線程順序查詢32分庫的數(shù)據(jù),但是數(shù)據(jù)量太大,執(zhí)行第一步查詢的耗時超過了預(yù)期,必須要32分庫并發(fā)查詢。
解決辦法:
- 啟動32個子進程并發(fā)去查詢每個分庫的結(jié)果
- 通過hive命令執(zhí)行map-reduce任務(wù)查詢HDFS冷備份的數(shù)據(jù)
這里查詢的32個分庫并不是指的用戶日常讀寫分離的主從庫,而是為了給開發(fā)人員查詢數(shù)據(jù)而提供的一份從庫,該從庫不會給線上環(huán)境的用戶使用,因此慢查詢也不會影響線上業(yè)務(wù)的使用。除此以外,這32個分庫每天在凌晨1點執(zhí)行sqoop任務(wù)將全量mysql數(shù)據(jù)轉(zhuǎn)儲到HDFS上作為hive表使用。整體的數(shù)據(jù)庫拓撲邏輯如下:
數(shù)據(jù)加工生成的sql語句注意特殊符號
sql文件按照預(yù)期正常生成了,但是在執(zhí)行過程中發(fā)生了錯誤,部分語句無法正常執(zhí)行,筆者生成的sql語句大概形如
update tb set lastname='xxx' where userid=123 and pkid=555 and fullname='yyyxxx';
經(jīng)過排查,發(fā)現(xiàn)失敗的原因是部分update語句中生成的字符串含有特殊符號,例如包含'、\、 不可見字符導致顯示為? 的情況,會導致mysql語句解析錯誤執(zhí)行失敗。
解決辦法:
對這些特殊字符進行轉(zhuǎn)義,對于篩選條件中可能出現(xiàn)的不可見字符顯示為問號的情況,將='xxx???'改為like 'xxx___',對于設(shè)置條件中可能出現(xiàn)不可見字符的情況報錯(不過這種情況我們確實無能為力,只能從源頭排查不可見字符的業(yè)務(wù)來源了,所幸筆者并沒有碰到這種情況)
最后語句如下:
update tb set lastname='xxx' where userid=123 and pkid=555 and full name like 'yyyxxx';
| 特殊字符 | 轉(zhuǎn)義方式 |
|---|---|
' |
\' |
= 'xxx?' |
like 'xxx_' |
\ |
\\ |
在sql語句中每隔1000條sleep 1s防止主從延遲
這條不是筆者踩的坑,不過后續(xù)刷數(shù)據(jù)也應(yīng)該要注意,因為刷數(shù)據(jù)操作的頻率過快可能會導致binlog數(shù)量突增,大量刷數(shù)據(jù)的binlog占據(jù)了主從同步的隊列,導致真正用戶自己的操作也被延遲,由于讀寫分離的架構(gòu)導致了寫完后讀不到最新結(jié)果,會十分影響業(yè)務(wù)。
一般是采用每1000條udpate語句中間執(zhí)行一句select sleep(1);