前言:如果是第一次安裝使用datax,或您服務器Mysql版本是 <= 5.7的,請先參考我之前的隨筆:https://www.cnblogs.com/zifan/p/9194793.html。
背景:Mysql從5.6升級到8.0.19之后,發現原先正常跑的datax出錯了。
先來看下我的報錯信息:(看不清請放大網頁)

1 2020-03-18 10:00:10.038 [0-0-0-writer] ERROR StdoutPluginCollector - 2 java.sql.SQLException: Could not retrieve transation read-only status server 3 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:996) ~[mysql-connector-java-5.1.34.jar:5.1.34] 4 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:935) ~[mysql-connector-java-5.1.34.jar:5.1.34] 5 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:924) ~[mysql-connector-java-5.1.34.jar:5.1.34] 6 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:870) ~[mysql-connector-java-5.1.34.jar:5.1.34] 7 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:902) ~[mysql-connector-java-5.1.34.jar:5.1.34] 8 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:892) ~[mysql-connector-java-5.1.34.jar:5.1.34] 9 at com.mysql.jdbc.ConnectionImpl.isReadOnly(ConnectionImpl.java:3607) ~[mysql-connector-java-5.1.34.jar:5.1.34] 10 at com.mysql.jdbc.ConnectionImpl.isReadOnly(ConnectionImpl.java:3576) ~[mysql-connector-java-5.1.34.jar:5.1.34] 11 at com.mysql.jdbc.PreparedStatement.checkReadOnlySafeStatement(PreparedStatement.java:1114) ~[mysql-connector-java-5.1.34.jar:5.1.34] 12 at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1134) ~[mysql-connector-java-5.1.34.jar:5.1.34] 13 at com.alibaba.datax.plugin.rdbms.writer.CommonRdbmsWriter$Task.doOneInsert(CommonRdbmsWriter.java:382) [plugin-rdbms-util-0.0.1-SNAPSHOT.jar:na] 14 at com.alibaba.datax.plugin.rdbms.writer.CommonRdbmsWriter$Task.doBatchInsert(CommonRdbmsWriter.java:362) [plugin-rdbms-util-0.0.1-SNAPSHOT.jar:na] 15 at com.alibaba.datax.plugin.rdbms.writer.CommonRdbmsWriter$Task.startWriteWithConnection(CommonRdbmsWriter.java:297) [plugin-rdbms-util-0.0.1-SNAPSHOT.jar:na] 16 at com.alibaba.datax.plugin.rdbms.writer.CommonRdbmsWriter$Task.startWrite(CommonRdbmsWriter.java:319) [plugin-rdbms-util-0.0.1-SNAPSHOT.jar:na] 17 at com.alibaba.datax.plugin.writer.mysqlwriter.MysqlWriter$Task.startWrite(MysqlWriter.java:78) [mysqlwriter-0.0.1-SNAPSHOT.jar:na] 18 at com.alibaba.datax.core.taskgroup.runner.WriterRunner.run(WriterRunner.java:56) [datax-core-0.0.1-SNAPSHOT.jar:na] 19 at java.lang.Thread.run(Thread.java:748) [na:1.8.0_241] 20 Caused by: java.sql.SQLException: Unknown system variable 'tx_read_only'
只需關注第一行和最后一行。第一行你去百度,部分資料會告訴你讓你設置下數據庫“事務隔離級別”,參考:https://www.cnblogs.com/jeffen/p/6005410.html
SET GLOBAL transaction_isolation='READ-COMMITTED';
本人也嘗試過,對Mysql8而言報錯依舊,不過其它mysql版本可以嘗試該解決方案。參考:https://www.cnblogs.com/lewic/p/10685004.html,發現最終原因應該還是驅動版本不問題。
再來關注最后一行:java.sql.SQLException: Unknown system variable 'tx_read_only',大部分的資料表明是驅動版本不一致的問題。總結以上,致命原因只有一個,就是“mysql的驅動版本不對”,所以解決方案自然就是升級驅動了。
首先查看下原來的驅動:
ll {%Datax_Path}/plugin/writer/mysqlwriter/libs/ | grep mysql-con
截至2020/03/23,GitHub上下載的最新datax tar包 所包含的mysql驅動是mysql-connector-java-5.1.34.jar。的確不匹配啊,此時有人會第一時間想到從網上直接下載8的驅動丟進去或替換就好了,
參考:https://blog.csdn.net/jason_9527/article/details/100995505
思路沒問題,不過不能徹底解決問題,而且會有一些error、warning出來。比如:
1、ERROR: zeroDateTimeBehavior=convertToNull要改為CONVERT_TO_NULL
2、WARN: Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary. 3、WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
所以我們要采用“修改源碼,自行編譯”的方式來徹底解決所有問題。參考:http://www.manongjc.com/detail/14-iexdburliccybhe.html
第一步下載源碼:
git clone方式或直接https://github.com/alibaba/DataX/archive/master.zip下載。
第二步修改mysql-connector-java驅動的版本號:
找到位於 {DataX_source_code_home}/mysqlreader/ 和 {DataX_source_code_home}/mysqlwriter/ 下的pom.xml文件,將version的值改為8.0.X(可以直接搜索‘mysql-connector-java’快速定位,X寫你自己想要的版本號)
如果你只用到了mysql的寫,可以只修改mysqlwriter目錄下的xml文件。
第三步修改zeroDateTimeBehavior的值convertToNull 為 CONVERT_TO_NULL:
編輯{DataX_source_code_home}/plugin-rdbms-util/src/main/java/com/alibaba/datax/plugin/rdbms/util/DataBaseType.java
全文替換 convertToNull 為 CONVERT_TO_NULL
# 自行檢索 {DataX_source_code_home}/文件夾下所有包含convertToNull字符串的文件,定位到文件再替換
vim {DataX_source_code_home}/plugin-rdbms-util/src/main/java/com/alibaba/datax/plugin/rdbms/util/DataBaseType.java # 然后命令模式下全文替換 :%s/convertToNull/CONVERT_TO_NULL/
到此,如果跳過第四、五步直接打包datax,程序已經能正確運行,如果想完美解決其他警告,請按步驟繼續。
第四步修改jdbc驅動的名稱com.mysql.jdbc.Driver 為 com.mysql.cj.jdbc.Driver
vi {DataX_source_code_home}/plugin-rdbms-util/src/main/java/com/alibaba/datax/plugin/rdbms/util/DataBaseType.java vi {DataX_source_code_home}/adswriter/src/main/java/com/alibaba/datax/plugin/writer/adswriter/load/AdsHelper.java
全文替換 com.mysql.jdbc.Driver 為 com.mysql.cj.jdbc.Driver。
第五步jdbc鏈接追加useSSL=false設置:
比如:python datax.py file.json , 則file.json的配置項:"jdbcUrl":"jdbc:mysql://${writer_gateway}/oms?useUnicode=true&characterEncoding=UTF-8&useSSL=false",
第六步通過maven打包:(本人是參考Git上開發者提供的操作步驟來的)
cd {DataX_source_code_home} mvn -U clean package assembly:assembly -Dmaven.test.skip=true
打包成功,日志顯示如下:
[INFO] BUILD SUCCESS
[INFO] -----------------------------------------------------------------
[INFO] Total time: 08:12 min
[INFO] Finished at: 2015-12-13T16:26:48+08:00
[INFO] Final Memory: 133M/960M
[INFO] -----------------------------------------------------------------
打包成功后的DataX包位於 {DataX_source_code_home}/target/datax/datax/ ,查看datax/plugin/writer/mysqlwriter/libs/目錄,已經包含新版的驅動jar包
最后一步:
就是把datax移動到你希望的位置,然后執行:python datax.py ./file.json,至此,OVER