GaussDB(DWS)迁移 -数据迁移 - 使用Spark的scala接口往GaussDB(DWS)导入数据失败分析

譡里个檔 发表于 2021/03/29 20:48:11 2021/03/29
【摘要】 使用Sprak的scala接口往GaussDB(DWS)导入数据时,当数据源表和目标表数据不一致时,可能会触发导入作业异常

【问题场景】

某局点使用Sparkscala接口从hiveGaussDB(DWS)进行大批量数据导入的时候,必然出现下面的报错导致数据导入任务失败


导数脚本如下:

scala> val df = spark.read.table("CTE_REP.TEST").limit(1000000).repartition(6).toDF()
scala> df.write.mode("Overwrite").jdbc("jdbc:postgresql://10.60.178.127:25308/postgres", "CTE_REP.test", t1)


同时客户确认相同的程序从hivePostgesSQL导入数据的时候没有出现此类异常


【问题原因】

使用Spark的scala接口进行抽数操作时,如果数据源端的表定义中某个字段的数据类型和数据目标端的表定义中对应字段的数据类型不匹配,那么Spark代码逻辑在处理NULL值和非NULL值时可能会出现逻辑冲突。具体为

  • 对于非null值,使用函数makeSetter绑定参数值
  • 对于null值,调用 getJdbcType来绑定null值

从上面代码可以看到函数getJdbcType和makeSetter都有一个入参dialect,这里的dialect(方言,这里的意思是要写入的数据库,比如OraclePostgreSQLdb2teredata)跟底层参数值的bind逻辑强相关。而出问题的集群上使用GaussDB(DWS)的驱动为gsjdbc200.jar,不在Spark内部注册的dialect范围(当前Spark内置注册的dialectdb2mysqloracleteredatapostgresqlSqlServerDerby)内。当同一个batch的数据的某个字段同时出现了null值和非null值的时候,会导致同一个字段bind走进了两个代码分支,有可能bind了两个不同的数据类型,触发了PreparedStatement的两次parse(具体原因需要看jdbc源码,此处未深入走读),导致出现这个问题。


当Spark不识别驱动对应的dialect时,getJdbcType底层调用为函数getCommonJDBCType, 而CLOB在驱动gsjdbc200.jar中又被识别为OID,从而导致发生如上现象


对于db2、mysqloracleteredatapostgresqlSqlServerDerby这几种Spark内置支持的几种dialectSpark代码中进行了特殊处理,在某些特性场景下会规避此类问题,降低问题出现的概率。

 

Spark对于Oracle的特殊处理如下:

Spark对于PostgreSQL的特殊处理如下:

 

【触发因素】

针对上述分析,结合现网场景进行排查,确定现网场景下具体触发因素如下

  • 数据源端的hive中表test的字段 report_dt的数据类型是string
  • 数据目标端GaussDB(DWS)中表test的字段 report_dt的数据类型是timestamp
  • 同一个批次导入的数据中,表test的report_dt字段出现了NULL值和非NULL值
  • GaussDB(DWS)使用的驱动包是gsjdbc200.jarSpark无法识别此方言

 

【处理建议】

  • 保证源端和目标端的表定义的字段顺序和数据类型一致

 

【附-GaussDB(DWS)驱动说明】

GaussDB(DWS)提供gsjdbc4.jargsjdbc200.jar两个驱动,它们的区别在于

  •  gsjdbc4.jar:与PostgreSQL保持兼容的驱动包,其中类名、类结构与PostgreSQL驱动完全一致
  •  gsjdbc200.jar:如果同一JVM进程内需要同时访问PostgreSQLGaussDB(DWS),请使用此驱动包。它的主类名为“com.huawei.gauss200.jdbc.Driver(即将“org.postgresql”替换为“com.huawei.gauss200.jdbc),数据库连接的URL前缀为“jdbc:gaussdb”,其余与gsjdbc4.jar相同


大尾标.png



【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区),文章链接,文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:cloudbbs@huaweicloud.com进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。