定时同步变慢主因是全量读写导致I/O与内存压力,应设chunksize、复用engine、禁用自动类型推断;DataX卡住多因Hive小文件或MySQL超时,需调参分片;增量优选自增ID而非时间戳;Kettle假死需状态文件+超时控制;位点必须持久化。
用 APScheduler + pandas 做定时同步,为什么越跑越慢?
不是调度器的问题,而是每次全量读取+全量写入导致 i/o 和内存持续吃紧。尤其当源表超 500 万行时,pandas.read_sql 默认不设 chunksize,会一次性把整张表加载进内存,接着 to_sql 又默认逐行插入——这两步叠加,同步耗时可能从秒级涨到分钟级。
- 务必在
read_sql中显式传chunksize=10000,配合迭代处理,避免 OOM -
to_sql必须加if_exists='append'和method='multi'(MySQL)或使用postgresql的execute_batch(需 sqlalchemy 2.0+) - 禁用 pandas 自动类型推断:
dtype参数显式声明字段类型,否则每 chunk 都要重推,CPU 白耗 - 不要在循环里反复创建
engine;复用连接池,设置pool_pre_ping=True防连接失效
DataX 做 MySQL → Hive 同步卡在 85%,怎么破?
这不是数据没传完,而是 Hive 端小文件过多触发了底层 HDFS 写入阻塞,或者 MySQL 侧 long_query_time 设置过低,导致 Reader 被频繁中断重试。
- 检查 DataX 日志中是否出现
Too many small files或Connection reset;前者调大writeMode: "overwrite"+postSql合并小文件,后者调高 MySQL 的wait_timeout和max_allowed_packet - 在
job.content[0].reader.parameter中启用where条件分片,例如"where": "id % 4 = 0",配合 4 个 channel 并行,比单 channel +splitPk更稳 - Hive Writer 必须关掉
compress(除非你真需要压缩),否则 LZ4/GZIP 会吃光 CPU,反拖慢吞吐 - 避免在 Hive 表上开事务(ACID 表),DataX 不兼容,会静默失败
增量同步用时间戳还是自增 ID?哪个更可靠?
时间戳看似简单,但跨库时区、NTP 偏移、批量更新覆盖等问题会让它变成“隐形炸弹”;自增 ID 更可控,但前提是源表主键严格单调递增且无删除重用。
- 优先选
auto-increment ID:同步时记录上一次最大id,下次查WHERE id > ?,无时区干扰,可精确断点续传 - 若只能用时间戳,必须统一源/目标库的
time_zone为+00:00,且所有写入都走 UTC 时间函数(如 MySQL 的UTC_TIMESTAMP()),不能依赖NOW() - 严禁用
UPDATE_TIME这类系统字段做增量依据——它不触发更新就不变,漏数据是常态 - 上线前做一次「双轨校验」:用全量比对脚本跑一遍最近 1 小时增量结果,确认无漏无重
Kettle 定时任务跑着跑着就假死,Linux 下怎么盯住它?
Kettle(PDI)本身不带健康心跳,Java 进程挂了也不会自动拉起,靠 crontab 单纯轮询 ps 很难捕获僵死状态——比如 Spoon 卡在 JDBC 连接等待,进程还在但无实际工作。
- 启动时加 JVM 参数:
-Dorg.pentaho.kettle.job.status.file=/tmp/kettle_job_status.json,让 Kettle 主动写运行状态到文件 - 用
curl -s http://localhost:9001/status(需启用 Carte server)或定期读取上述 JSON 文件判断"status": "running"和"lastUpdate"是否超时(如 >5 分钟无更新) - crontab 不要直接调
pan.sh,改用封装脚本:先timeout 300s ./pan.sh ... || killall -9 java,防僵尸残留 - 日志必须重定向到文件并按天轮转,别让
carte.log胀到几个 GB——Kettle 读大日志会卡住 UI 和 API
max_id 存在本地文件或内存里,一重启就丢,再同步就是全量重来。这问题不解决,性能再优也是白搭。











