ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

DataX MySQLReader深度解析:分片原理、配置实战与性能调优

DataX MySQLReader深度解析:分片原理、配置实战与性能调优 1. MySQLReader在数据同步里的位置它到底解决了什么问题先说一个场景。我一个朋友上个月被老板临时抓去导数据说有张业务表三千多万行要按指定条件抽出来给下游团队。他一开始图省事打开navicat全量导出Excel结果导到一半直接卡死电脑风扇转得跟飞机起飞似的。后来换成分页查询循环导出跑了一个多小时期间还因为特殊字符、字段类型问题断了好几次。他问我“用DataX的MySQLReader能不能一把梭”我说能而且你那套手动方案写出来至少三百行代码MySQLReader一行配置就解决了。这其实是DataX体系里最典型的场景。DataX是异构数据源离线同步工具核心逻辑就是“一个插件负责读、一个插件负责写”。Reader端负责从源端抽取数据Writer端负责把数据写入目标端。像MySQLReader和MySQLWriter就是最常用的组合。MySQLReader做的事情本质上是把你从“写JDBC代码、管连接、分页游标、封装数据、异常重试”这些脏活里解放出来你只需要用JSON声明“我要从哪个库、哪张表、按什么条件、用哪几个字段读数据”剩下的逐行读取、类型转换、并发切分、失败重试由框架统一消化。这里有一个关键认知MySQLReader不是一个“独立工具”它是DataX的插件脱离了DataX本身谈插件没有意义。所以这篇文章我默认你至少了解DataX的基本使用方式比如会配job.json、会用python运行任务。如果你连DataX是什么都不太清楚也没关系第二部分我会把部署和准备一起讲清楚但重点始终放在MySQLReader本身。MySQLReader适合谁来用我认为是这样几类人一是经常要做MySQL到MySQL、MySQL到HDFS、MySQL到数仓之间数据迁移的工程师二是做数据中台、数据集成平台需要把“同步能力”封装成组件的人三是刚接触DataX想搞明白Reader插件到底怎么干活、配置参数各是什么含义的人。写给这三类人看的东西不能只列参数手册得把参数背后的机制、常用的组合方式、真实的坑都讲透这样才能真正提高干活效率。具体来说MySQLReader能帮你完成的事情包括但不限于全量抽一张表按where条件增量抽取指定字段列抽取按主键或业务字段切分成多个并行通道抽取读取无主键表的全量数据把多个表抽到同一个目标。它甚至能处理MySQL特有的字段类型映射比如DATETIME、DECIMAL、BIGINT UNSIGNED这类容易出问题的类型。后面我会逐个拆解。2. MySQLReader的工作机制分片逻辑、游标读取与内存防线很多刚用DataX的人会有一个错觉MySQLReader就是把“select * from table”执行一下然后把结果集一坨交给Writer。如果真这么做根本撑不住大表抽取。MySQLReader内部有几个设计要点决定了它在大数据量下依然能稳定工作理解这些机制你才能明白哪些参数应该怎么调。2.1 数据分片线程数不是拍脑袋定的DataX的并发逻辑是一个Reader插件实例对应一个通道channel每个通道用独立线程去跑。多通道并行读取速度理论上可以线性提升。但MySQLReader怎么知道把一张表拆成几段来读这里有两种方式。方式一是配置项里的splitPk。你在Reader配置里指定一个字段作为拆分键DataX会执行类似SELECT MIN(splitPk), MAX(splitPk) FROM table的查询算出字段的取值范围然后根据通道数把这个范围切分成多个区间每个区间对应一段子查询。比如你有100万条数据要开10个通道如果splitPk是分布均匀的自增主键那每个通道大约处理10万条每个通道各跑各的where区间时间基本持平。方式二是不配splitPk。这时候DataX会退化成单通道读取全表所有数据压在一个线程里。别小看这个细节我见过不少人配了channel: 5但忘了配splitPk抱怨“怎么开了5个通道还是慢”。原因就在这——通道数是worker数量但一张表没有拆分键Reader就只能把整个表当一个整体交给一个worker去读其余worker空闲。所以如果你的表又没有主键又找不到合适的拆分字段多通道基本是个摆设。2.2 where条件不是只配给全表的MySQLReader的where参数可以做两件事一是全局过滤在拼接SQL时作为where条件加在查询后面用于增量抽取或者按业务条件过滤二是配合splitPk使用在分片时每个切分片段会和这个where条件做AND合并。常见的坑是很多人以为配置了splitPk之后where里的条件就失效了。实际上不会失效最终每个通道的SQL大致是SELECT 字段 FROM 表 WHERE (splitPk start AND splitPk end) AND (你的where条件)。所以如果你要按“更新时间大于昨天”做增量且又需要分片并行两个条件是可以同时生效的。这也是我强烈建议增量任务最好找数字型或日期型字段做splitPk的原因——既能并行又能过滤一举两得。2.3 游标读取与ResultSet的取舍MySQLReader底层用的是JDBC的ResultSet。这里有一个常见的隐性性能问题MySQL JDBC驱动默认会把查询结果一次性存到内存里俗称“客户端缓存”。如果一张表几百万行这个内存占用是灾难级的。MySQLReader通过设置useCursorFetchtrue和合理的fetchSize来规避这个坑把查询改成服务端游标逐批读取。看到这会有人问DataX不是同步工具吗为什么还要考虑结果集内存因为DataX的通道是一个管道Reader产出的数据会缓冲在内存环形队列里然后再由Writer消费。如果源端一次吐几百万行内存环形队列根本挡不住。所以对流式读取的支持实际上是在源端做第一道内存防线。你在jdbcUrl里看到的useCursorFetchtruefetchSize256这类参数千万别删那是保命配置。2.4 类型转换的隐形规则MySQLReader读出来的数据并不是原封不动交给Writer的。每个字段都会经过DataX内部类型系统做一次规范化转码映射成DataX自己的类型体系。比如MySQL的TINYINT会转成LongDECIMAL转成DoubleDATETIME转成Date。这个转换过程对大多数场景是透明无感的但有两个类型需要特别警惕。第一个是BIT(1)在MySQL里常用于布尔值。这个类型通过MySQLReader读出后如果Writer端没做映射很可能会变成byte[]类型导致下游写入失败。第二个是DECIMAL转Double的精度损失问题。如果你的业务字段是18位以上的decimal值用默认映射会丢精度必须靠writer端的转换规则或者预先把字段转成varchar再同步。换句话说选字段时需要考虑源端到目标端的类型链而不是无脑select *。3. 环境准备与本地部署没有这一步后面全是空谈因为“datax 本地部署”属于高频搜索词我专门花一节把环境准备讲透。你要是已经跑通过DataX这节可以快速扫一眼要是全新环境请老老实实跟着做不然到后面报错你会想摔键盘。3.1 JDK版本与基础依赖DataX官方推荐的是JDK 1.8这几乎是圈内共识。虽然Oracle JDK、OpenJDK、Temurin都能跑但我个人建议用JDK 8对应版本原因不是“新版跑不了”而是DataX的插件体系在JDK 9以上遇到过模块化限制比如有些反射调用、Class.forName加载驱动的方式在更高版本上会报InaccessibleObjectException。你如果不想折腾就老老实实用8。版本确认很简单java -version看一下如果连Java环境都没有先去装一个。装完之后设置JAVA_HOME环境变量DataX启动脚本会主动去找这个变量找不到就默认走PATH里的java。这一步在Windows和Linux上操作略有区别原理一样。3.2 获取DataX包与周边工具DataX本身不需要编译源码直接下载打包好的发行版就能用。国内网络环境下如果从GitHub的release页面下载速度感人建议直接用加速镜像。下载完成后解压目录结构大概是datax/ bin/ datax.py conf/ core.json job/ lib/ plugin/ reader/ mysqlreader/ writer/ mysqlwriter/注意plugin/reader/mysqlreader这个目录它包含plugin.json和对应的jar包。在后面的任务调试中你可能会手动改这里的配置但日常使用不建议动。环境上还有一个小坑DataX的启动脚本datax.py依赖Python 2或Python 3中的print语法兼容。新版本DataX已经兼容Python 3但某些老版本只支持Python 2。如果你用的是CentOS自带Python 2.7问题不大如果你用的是比较新的发行版系统自带的可能就是Python 3。如果启动时报语法错误大概率就是版本问题解决方法有几种换用Python 2环境或者用python3 bin/datax.py命令试试。3.3 快速验证安装是否成功装好DataX后先别急着写MySQLReader的配置跑一个自带示例验证环境是否正常。执行python bin/datax.py job/job.json如果输出任务启动时刻、任务结束时刻、任务总计耗时这些信息说明部署成功。这一步能帮你区分“DataX本身坏了”还是“你的任务配置有问题”排查思路会清晰很多。部署阶段最常见的两个报错我这里提前打好预防针。第一个是ClassNotFoundException: com.mysql.jdbc.Driver我后面会专门拿一节讲这里只提一句大概率是mysql驱动jar没被正确加载。第二个是ConnectException这种要先查网络和端口不要一上来就怀疑DataX搞数据工具的都知道很多时候是MySQL侧把外部连接给拒了。4. 插件参数逐项拆解核心配置与最容易踩的字段类型坑MySQLReader的配置集中在job.json的reader段里。我见到过不少人在网上抄配置改个库名表名就开始跑跑不通之后也不知道是哪个参数没抄全。所以我挑几个关键参数逐个拆。4.1 job.json里的reader段长什么样下面是一个典型的MySQLReader配置段先有个整体印象{ job: { content: [ { reader: { name: mysqlreader, parameter: { username: root, password: your_password, column: [id, name, create_time], connection: [ { table: [user], jdbcUrl: [jdbc:mysql://127.0.0.1:3306/test_db?useUnicodetrueuseCursorFetchtruefetchSize256] } ], where: create_time 2024-01-01 00:00:00, splitPk: id } }, writer: { name: mysqlwriter, parameter: { username: root, password: your_password, column: [id, name, create_time], preSql: [truncate table user_copy], connection: [ { table: [user_copy], jdbcUrl: [jdbc:mysql://127.0.0.1:3306/test_db?useUnicodetrue] } ] } } } ], setting: { speed: { channel: 3 } } } }注意第一行name: mysqlreader这是插件目录名DataX会去plugin/reader/mysqlreader下加载对应实现类。如果你的插件目录名不匹配启动时会直接报plugin not found。这个看起来简单但真有人把名字改成了mysql_reader然后跑半天找不出问题。4.2 column显式选列是良心配置column既支持数组形式也支持[*]表示全列。我的建议是尽量显式列出需要的列而不是用*理由有二。第一是减少不必要的类型转换大表全字段抽取时那些你不关心的大字段比如TEXT、JSON会白白占用内存和IO第二是避免字段顺序变化带来的导出错位很多时候下游文件或表是按位置消费数据的显式声明相当于给数据字段上了保险。有一个特殊写法值得单独提column: [ id, concat(name, _, age), now() ]MySQLReader对列的解析不是简单的字段名罗列它支持函数表达式。你可以直接在column里写concat(...)、date_format(...)、now()这类服务端函数。这个特性在清洗数据时特别有用比如你不想在Writer端做二次加工直接在Reader的SQL层就完成拼串和格式化。但提醒一句除非必要别搞太复杂函数写多了会影响你对最终数据的判断排查问题时会多一层干扰。4.3 connection的jdbcUrl与table关系connection是一个数组数组里每个元素可以包含一张或多张表以及对应的jdbcUrl。每个connection下的表都会按相同连接参数去读。很多人第一次用的时候不理解为什么是数组套数组总想写成字符串结果解析报错。其实jdbcUrl设计成数组主要是为了以后支持多地址负载目前你填一个地址就够了但格式上要用[jdbc:mysql://...]。table数组则支持你在同一个连接串下读取多张表比如table: [user, user_copy]如果配置了多张表DataX默认会做Union合并读取。这个功能有时候很好用比如你要汇总几个月的分表数据到一张大表但要注意多表合并后字段数必须一致且字段顺序有意义对应否则下游写入很容易错位。4.4 常见的MySQL类型映射对照我把MySQLReader默认的类型映射整理成一张表方便你排查问题时对照MySQL类型DataX内部类型常见问题TINYINT/SMALLINT/INT/BIGINTLong无符号类型可能溢出DECIMAL/NUMERICDouble大精度数据丢失FLOAT/DOUBLEDouble精度本身有限VARCHAR/CHAR/TEXTString无DATETIME/TIMESTAMPDate时区问题、格式问题DATEDate时分秒为0BIT(1)byte[]转布尔时需额外处理BLOB/BINARYbyte[]大字段内存占用高JSONString5.7以上返回的是String注意最后一行JSON。MySQL 5.7以上版本中JSON列通过JDBC读出时基本是字符串格式DataX按String处理即可。但你如果手动在SQL里用了JSON_EXTRACT这类函数返回值类型是字符串下游字段如果是JSON类型可能会出现字符合法性校验不过的情况这就属于业务层问题不是插件bug。4.5 时区问题数据“凭空”慢了8小时MySQLReader读DATETIME时时间值来自MySQL连接的时区。如果你的jdbcUrl里没有配置serverTimezone而MySQL服务器和运行DataX的机器时区不一致读出来的时间对象可能出现偏移。比如MySQL是CST东八区DataX机器是UTC你把读出来的时间交给下游转换会发现所有时间都慢了8小时。解决办法是在jdbcUrl里显式声明jdbc:mysql://127.0.0.1:3306/test_db?useUnicodetrueserverTimezoneAsia/ShanghaiuseCursorFetchtruefetchSize256serverTimezoneAsia/Shanghai重点加粗一下。这个问题在跨机房、跨云环境的同步中特别常见而且它不会报错只会静默产生错误数据——属于最阴险的坑之一。5. 从配置到跑通一个完整任务的最小可用实例讲完参数现在走一个完整流程让一个从没接触过的人也能照着敲出来跑通。5.1 准备源表和目标表先在MySQL里造一张源表order_infoCREATE TABLE order_info ( id BIGINT PRIMARY KEY, order_no VARCHAR(64), user_id BIGINT, amount DECIMAL(10,2), create_time DATETIME );插入一些测试数据然后创建目标表order_info_backup结构保持一致。这一步的目的是把变量降到最少——先跑通最简单的结构再叠加条件、函数、分片这些高级玩法。5.2 编写最小job配置{ job: { content: [ { reader: { name: mysqlreader, parameter: { username: root, password: 123456, column: [id, order_no, user_id, amount, create_time], connection: [ { table: [order_info], jdbcUrl: [jdbc:mysql://127.0.0.1:3306/test_db?useUnicodetruecharacterEncodingutf8useCursorFetchtruefetchSize256] } ] } }, writer: { name: mysqlwriter, parameter: { username: root, password: 123456, column: [id, order_no, user_id, amount, create_time], preSql: [truncate table order_info_backup], connection: [ { table: [order_info_backup], jdbcUrl: [jdbc:mysql://127.0.0.1:3306/test_db?useUnicodetruecharacterEncodingutf8] } ] } } } ], setting: { speed: { channel: 1 } } } }注意Writer里我加了一个preSql作用是每次任务开始前先清空目标表。这个操作在重复跑任务时非常重要否则数据会累积重复。当然如果你想要的是追加模式而不是覆盖模式就别加这条truncate语句。5.3 执行任务并解读日志python bin/datax.py job/mysql_reader_demo.json跑起来之后日志里重点看三个信息。第一个是Channel: 1确认并发通道数符合预期第二个是任务总耗时和平均流量这是后续调优的基线第三个是同步失败记录数如果该数字大于0需要去日志里找具体的脏数据原因。第一次跑通常会遇到的问题是驱动加载失败。DataX的mysqlreader默认依赖的MySQL驱动版本是5.1.x如果你的MySQL是8.0以上注意服务端连接可能因为认证插件问题报错。此时建议去maven仓库下载对应版本的mysql-connector-java jar替换掉plugin/reader/mysqlreader/libs目录下的旧jar。这个操作不复杂先把旧的备份再把新的扔进去重启任务即可。5.4 加入增量条件与分片全量跑通后再把增量场景也验证一遍。把reader段的where参数加进去where: create_time 2024-06-01 00:00:00 AND create_time 2024-06-02 00:00:00同时因为源表有主键id我们可以加上splitPk: id,并把setting.speed.channel改成3setting: { speed: { channel: 3 } }这样跑的SQL大概等价于三个区间并行执行整体耗时会比单线程快不少。我实测过一张500万行的表单通道跑了大概4分钟3通道配合splitPk大概1分40秒提升还是很明显的。当然提升幅度受制于表数据分布均匀度和MySQL服务器的并发能力如果你的id自增分布有大量空洞切分区间会不均可能达不到理论提速值。6. 实战排障我遇到过的五个高频坑与排查链路这一节是我最想写的部分。参数文档谁都能查但真实环境里的坑文档大概率不会告诉你。以下五个问题是我在不同项目里真实踩过的每一个都花过不少时间排查希望大家看完能少走弯路。6.1 坑一ClassNotFoundException驱动加载失败场景任务一启动就报错日志里明确出现ClassNotFoundException: com.mysql.jdbc.Driver。原因分析DataX的MySQLReader插件所用jar包路径是plugin/reader/mysqlreader/libs里面默认带了mysql驱动。为什么还会找不到类两种情况一是你换过jar包但路径放错了比如放到了plugin/reader而不是plugin/reader/mysqlreader/libs二是驱动类名确实没有被插件加载器扫描到。排查链路建议第一步确认jar是否存在于正确目录第二步解压jar确认里面META-INF/services或驱动主类是否完整第三步换一个更高版本的驱动比如mysql-connector-java-8.0.x.jar但8.x版本的驱动类名变成了com.mysql.cj.jdbc.Driver如果数据源里还写老的com.mysql.jdbc.Driver要同步改掉。6.2 坑二无主键表配splitPk导致区间切分失败场景一张日志表没有主键你给splitPk随便指定了一个普通字段任务启动时卡在区间计算阶段日志出现Please check splitPk或data source error。原因分析MySQLReader执行SELECT MIN(splitPk), MAX(splitPk) FROM table时如果指定字段类型不支持范围比较或字段数据库类型是TEXT、VARCHAR的无序值切分就会失败。还有一种常见情况是表数据量过大但字段值大量重复切出来的区间严重倾斜某个通道跑完了其他通道还在吭哧吭哧。处理方案a给表加一列自增代理键或选用唯一数字型字段b实在没有合适字段就放弃splitPk单通道跑用batchSize补偿c如果只是增量同步可以用where条件缩小数据量再分片。总之不要让DataX对无规律字段做范围切分。6.3 坑三大字段导致Size Exceeded场景表里有MEDIUMTEXT或BLOB列任务跑到一半报Record size exceeded之类的错误。原因分析DataX的每条记录在通道里是有大小上限的核心配置byteLimit和记录相关的上限设置决定了单条记录能否被完整承载。大字段如果超过限制就会判定为脏数据或直接报错。处理方案有三个方向。一是在Reader的column里剔除不需要的大字段这是最省事的二是调大相关上限参数比如在core.json或job的setting里把小字段的内存限制调高三是把大字段写到文件或对象存储只同步元数据字段。最后这个方案适合必须保留大字段内容的场景相当于先抽出“指针”再单独搬运实体内容。6.4 坑四增量同步的重复与漏数场景用where按create_time做增量同步但重复跑了几天后发现数据有重复和漏数。原因分析增量同步的关键不只是where条件还得确定你的时间字段是否能追加更新。create_time是插入时间update_time才是修改时间。如果你的业务表只有create_time而没有update_time老数据被修改后增量同步根本不会感知到变化漏数几乎必然。另一方面如果where条件用的是每次任务间隔内的边界数据会被重复抽取比如上次抽到2024-06-01 23:59:59下次起点还是2024-06-01 00:00:00那全天数据又扫一遍。处理方案使用和半开区间比如每次抽取[last_max_time, current_time)同时记录本次任务中最大的时间戳作为下轮起点。最好再加一个主键或唯一键去重逻辑目标表用upsert而不是纯insert。很多时候DataX任务本身没问题是任务调度边界设计有问题这块建议大家在设计阶段就投入精力。6.5 坑五与同期跑的写库任务互锁场景DataX任务读取一张MySQL业务表但线上同时有另一个任务在批量更新这张表导致读取时不时报Lock wait timeout exceeded。原因分析MySQLReader默认的查询不加锁但如果查询走了某些隔离级别或者数据量特别大导致扫描时间长整体上会放大与写事务的竞争。常见原因是DataX在读取时占用大量数据库连接和IO线上更新事务被长时间阻塞最终超时。处理方案一是尽量在备库上跑抽取任务这是最优雅的二是控制通道数和fetchSize降低源库压力三是把读取任务放在业务低峰期。对于无法避免的情况可以考虑先用mysqldump或临时表方式把快照导出再交给DataX做后续转换。7. 性能调优的取舍线程、批量、内存之间的平衡性能调优是每篇DataX相关文章都逃不掉的话题。但我想表达一个观点调优的本质不是无脑开线程而是在“源库承受能力、网络带宽、目标端写入能力、JVM内存上限”中间找平衡点。这节会把主要的加速旋钮讲明白。7.1 channel数与splitPk的配合是第一优先级先看一个典型配置setting: { speed: { channel: 5 } }设了5个通道MySQLReader这边如果不配splitPk这5个通道只有第一个真正在干活其余四个看着是Parallel实际上全在空转。所以在MySQLReader语境下谈channel数必谈splitPk两者是一体的。通道数的经验值我一般建议从3起步慢慢加到5、8观察数据库侧监控如果Threads_running和CPU没有明显飙升再继续加。有一类情况必须谨慎加通道源表是超大宽表每条记录就有好几KB5个通道并发时的内存占用很可能直接打爆JVM。这时候宁可通道少点、batchSize大点反而更稳。7.2 内存参数与JVM调优DataX默认的JVM启动参数在bin/datax.py脚本里可以调核心是-Xms和-Xmx。默认值一般是1G或2G。当你的任务涉及大表抽取和宽表记录时内存不够的表现是OOM或者Full GC频繁。我遇到过一张表平均单行8KBchannel开到5内存默认1G跑了二十分钟后任务直接卡死GC日志刷屏。建议做法是看单行大小和通道数的乘积估算内存需求再留出缓冲。比如单行8KB、一次每个通道缓冲2万条5个通道大约800MB算上前期缓冲和网络包2G起步比较稳。我常用的是python bin/datax.py job.json --jvm-Xms2g -Xmx4g注意--jvm参数是传给DataX启动器使用的JVM选项不是任务配置。如果你是在脚本里封装了DataX调用这种传参方式要保留好。7.3 fetchSize与batchSize的关系前面提到了useCursorFetchtruefetchSize256这是Reader端每次从数据库抓取的行数。fetchSize设置太小比如64网络请求次数会增多设置太大比如8192虽然减少了往返次数但单次内存占用增加也容易造成数据库端临时表压力。256是一个相对保守的起步值大多数场景不用动。Writer端的batchSize控制一批写入的行数默认在个别writer插件里可能偏小。如果目标端也是MySQL批量insert一次50行左右是比较常见的起步值可以逐步加大看目标库响应时间。这里要说一个容易忽略的点Reader的fetchSize和Writer的batchSize不是一回事前者控制读口流量后者控制写口流量两者并不要求相等。调优时要分别看吞吐瓶颈在哪端别一上来两个一起乱调。7.4 脏数据阈值与中断策略DataX默认支持记录脏数据错误记录会单独写到脏数据文件同时任务不会立刻中断。但如果脏数据特别多整个任务的耗时会被拖长且目标端可能已经写入大批半成品数据。如果任务场景允许建议setting.speed里设置合理的错误记录上限或者利用errorLimit配置让脏数据过多时及时中断。例如errorLimit: { record: 0, percentage: 0.02 }表示允许2%的脏数据率超过就失败。这样既能容忍少量异常行又能防止问题扩大。我见过不少团队上线时不配errorLimit结果一次脏数据比例过高任务跑了一晚上才发现数据大面积异常回滚成本极高。对于上线初期的任务严格一点比宽容一点更安全。7.5 性能测试的对比方法最后给一个调优思路调参建议一次只动一个变量记录当前耗时基线再对比下一次。我自己的标准流程是先用默认配置跑记录总耗时和平均流量再加splitPk和channel3记录再调整fetchSize和batchSize再记录最终选一个稳定且符合源库压力的组合。用Excel把几次结果列成表你会发现很多看似玄学的性能问题其实都是参数变量叠加导致的一次动一个才能定位真正起作用的参数。另外MySQLReader性能受源库侧限制影响很大同样是500万行跑在自建库和跑在云数据库RDS上的最优参数差异可能很大。建议上生产前在目标环境完整跑一次压测不要照搬别人文章里的方案环境变量不同结果完全不同。在我的实际使用体验里MySQLReader是DataX生态里最成熟稳定的Reader之一。一旦理解了它的分片、游标、类型映射几个核心机制配起任务来基本不会再出大问题。如果你刚开始接触建议从一个最小的全量任务跑起逐步叠加where和splitPk再考虑性能和脏数据控制。等到你能熟练地用一个JSON完成百万行级别的迁移时会发现手动写代码抽数已经是一个没有必要再去重复的选项了。
返回列表