【问题标题】:MYSQL Warning in Client but Error in JDBC Connection from Spark客户端出现 MYSQL 警告,但 Spark 的 JDBC 连接出错
【发布时间】:2021-01-03 02:36:39
【问题描述】:

我正在编写一个 spark 代码以从数据帧插入到 mysql 表中,但出现错误

df_to_write.write.format("jdbc").option("url", jdbc_url).option("driver", "com.mysql.jdbc.Driver")\
          .option("dbtable", tbl_name).option("user", DBUser).option("password", DBPassword)\
          .option("numPartitions",32).mode('append').save()

org.apache.spark.SparkException: Job aborted due to stage failure: Task 1 in stage 18.0 failed 4 times, most recent failure: Lost task 1.3 in stage 18.0 (TID 170, 10.151.244.77, executor 0): java.sql.BatchUpdateException: Data truncation: Incorrect datetime value: '1970-01-01 00:00:00' for column 

这是我发现的,因为列的值为 1970-01-01 00:00:00

但是,如果我在 mysql 工作台中运行插入语句,它会发出警告,并且值被插入为 0000

示例如下:

create table test_time (processing_ts timestamp NULL DEFAULT NULL);

insert into test_time values ('1990-01-01T00:00:00.000+0000'),('1990-01-01T00:00:00.000+0000'),('1970-01-01T00:00:00.000+0000');

表格输出的值如下

1990-01-01 00:00:00
1990-01-01 00:00:00
0000-00-00 00:00:00     --> no error only warning and changed the value to 0000:00:00 00:00:00

想知道我可以在 spark 上应用什么设置来获得相同的行为,即应该没有错误并且值应该设置为 0000-00-00 00:00:00。 无论如何在写入表时在火花中应用插入忽略选项。

根据评论,粘贴代码进行仿真

SQL

mysql> create table test (processing_ts timestamp null);
Query OK, 0 rows affected (0.05 sec)

mysql> select * from test;
+---------------------+
| processing_ts       |
+---------------------+
| 1997-02-28 10:30:00 |
+---------------------+
1 row in set (0.00 sec)
df = spark.createDataFrame([('1970-01-01 00:00:00',)], ['processing_ts'])
df2 =  df.select(f.to_timestamp(df.processing_ts, 'yyyy-MM-dd HH:mm:ss').alias('processing_ts'))

db_host = '127.0.0.1'
DBName = 'test'
jdbc_url = "jdbc:mysql://{}/{}".format(db_host ,DBName)
DBUser = 'XXXXXX'
DBPassword = 'XXXXXXX123'
tbl_name = 'test'

df2.write.format("jdbc").option("url", jdbc_url).option("driver", "com.mysql.jdbc.Driver")\
          .option("dbtable", tbl_name).option("user", DBUser).option("password", DBPassword)\
          .option("numPartitions",32).mode('append').save()

【问题讨论】:

  • 使用 df_to_write.printSchema 和您面临问题的 MySQL 列数据类型提供数据框的架构。
  • @ShreyJakhmola 添加了模拟问题的步骤

标签: mysql apache-spark jdbc pyspark databricks


【解决方案1】:

TIMESTAMP 值的范围是 1970-01-01 00:00:01.0000002038-01-19 03:14:07.999999 MySql Doc

JDBC 驱动程序可能无法处理相同的问题,因此它正在中止插入作业。您唯一可以做的就是在插入之前将时间戳1970-01-01 00:00:00 替换为另一个虚拟时间戳,或者将列 processing_ts 的数据类型转换为 DATETIME,因为支持的范围是 1000-01-01 00:00:009999-12-31 23:59:59

【讨论】:

  • 我了解 TIMESTAMP 字段的限制,我想了解为什么如果我从客户端(mysql 工作台)运行相同的插入不会导致错误,而是截断日期,如上例所示。从 spark 加载时是否有任何选项可以忽略这些错误
  • 正如我所说,您用于从 spark 加载数据的 JDBC 驱动程序似乎无法处理上述情况,因此会引发错误。因此,这不是火花问题,而是您用来加载的驱动程序。将时间戳替换为虚拟时间戳或将目标列数据类型更改为 DateTime。要进一步调试,请指定用于将数据从 spark 加载到 MySQL 的驱动程序类或 jar。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 2019-07-14
相关资源
最近更新 更多