美文网首页MySQL大数据spark
spark-mysql:SQLException: Subque

spark-mysql:SQLException: Subque

作者: 利伊奥克儿 | 来源:发表于2019-03-28 17:36 被阅读1次

    SQLException: Subquery returns more than 1 row

    在工作中遇到一个写入数据库的问题
    写入数据库的dataFrame结构数据如下
    dataFrame1:

    sumDatemm c1 c2 c3 c4 c5
    201903281535 494708 255872 253937 11924 24844

    dataFrame2:

    sumDatemm c1 c2 c3 c4 c5
    201903280755 477217 218232 216556 9630 17430

    mysql的建表语句

    CREATE TABLE `TABLE_1` (
      `sumDatemm` text NOT NULL,
      `c1` bigint(20) NOT NULL,
      `c2` bigint(20) NOT NULL,
      `c3` bigint(20) NOT NULL,
      `c4` bigint(20) DEFAULT NULL,
      `c5` bigint(20) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8
    

    出现的错误

    在写第一条记录的时候没有出现问题
    但是第二条记录报了如下错误

    19/03/28 15:21:59 WARN scheduler.TaskSetManager: Lost task 3.0 in stage 322.0 (TID 8791, th04-ywy-hpdl380-057, executor 5): java.sql.BatchUpdateException: Subquery returns more than 1 row
            at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2024)
            at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1449)
            at org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils$.savePartition(JdbcUtils.scala:218)
            at org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils$$anonfun$saveTable$1.apply(JdbcUtils.scala:280)
            at org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils$$anonfun$saveTable$1.apply(JdbcUtils.scala:279)
            at org.apache.spark.rdd.RDD$$anonfun$foreachPartition$1$$anonfun$apply$33.apply(RDD.scala:920)
            at org.apache.spark.rdd.RDD$$anonfun$foreachPartition$1$$anonfun$apply$33.apply(RDD.scala:920)
            at org.apache.spark.SparkContext$$anonfun$runJob$5.apply(SparkContext.scala:1888)
            at org.apache.spark.SparkContext$$anonfun$runJob$5.apply(SparkContext.scala:1888)
            at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:66)
            at org.apache.spark.scheduler.Task.run(Task.scala:89)
            at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:242)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
            at java.lang.Thread.run(Thread.java:748)
    Caused by: java.sql.SQLException: Subquery returns more than 1 row
            at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)
            at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3597)
            at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3529)
            at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1990)
            at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2151)
            at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2625)
            at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2119)
            at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2415)
            at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1976)
            ... 14 more
    
    19/03/28 15:21:59 ERROR scheduler.TaskSetManager: Task 3 in stage 322.0 failed 4 times; aborting job
            at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2024)
            at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1449)
            at org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils$.savePartition(JdbcUtils.scala:218)
            at org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils$$anonfun$saveTable$1.apply(JdbcUtils.scala:280)
            at org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils$$anonfun$saveTable$1.apply(JdbcUtils.scala:279)
            at org.apache.spark.rdd.RDD$$anonfun$foreachPartition$1$$anonfun$apply$33.apply(RDD.scala:920)
            at org.apache.spark.rdd.RDD$$anonfun$foreachPartition$1$$anonfun$apply$33.apply(RDD.scala:920)
            at org.apache.spark.SparkContext$$anonfun$runJob$5.apply(SparkContext.scala:1888)
            at org.apache.spark.SparkContext$$anonfun$runJob$5.apply(SparkContext.scala:1888)
            at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:66)
            at org.apache.spark.scheduler.Task.run(Task.scala:89)
            at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:242)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
            at java.lang.Thread.run(Thread.java:748)
    Caused by: java.sql.SQLException: Subquery returns more than 1 row
            at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)
            at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3597)
            at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3529)
            at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1990)
            at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2151)
            at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2625)
            at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2119)
            at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2415)
            at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1976)
            ... 14 more
    

    分析问题

    从字面看来是返回的子查询结果多余一行,但是我本身插入的记录就只有一行,怎么会有多余一行的错误呢?
    于是把dataFrame的内容输出,结果也确实只有一条记录。
    况且我插入数据并没有查询的操作和过滤的条件,哪来的子查询呢?
    根据错误去度娘上搜一下,基本上答案都是一样的,都是类似下面的语句

    select * from table1 where table1.colums=(select columns from table2);
    (select columns from table2) 这一段的值有多个
    

    解决办法如下
    1)如果是写入重复,去掉重复数据。然后写入的时候,可以加逻辑判断(php)或者外键(mysql),防止数据重复写入。
    (我实际开发中遇到的就是数据重复写入的情况,在数据库查到有相同的数据两条,这不符原本的原本的业务需求)
    2)在子查询条件语句加limit 1,找到一个符合条件的就可以了
    select * from table1 where table1.colums=(select columns from table2 limit 1);
    3)在子查询前加any关键字
    select * from table1 where table1.colums=any(select columns from table2);
    [来源:关于mysql错误:Subquery returns more than 1 row]


    但是我在dataFrame写mysql的时候并没有类似的语句,貌似不是这个问题。
    百度、google了差不多一个小时都没区解决,只能求救队友了。

    高手分析问题

    跟同事说明相关情况
    尝试手动插入数据
    发现手动插入第二条记录也失败了
    再尝试拆如第一条记录,居然也失败了,可是在建表的时候可没有创建唯一键的
    根据报错猜测可能是某个字段重复导致失败,于是修改第一条记录某些字段的值,尝试插入数据。
    最后发现,c1这个列的值只要在数据库中有一样的数据就会失败。
    这个列有问题。

    定位问题
    后面去看了表格的详细信息
    发现这张表还有一个触发器,当这张表有插入新纪录的时候,会触发一个插入其他标的操作,其中涉及到了c1字段
    在看了触发器的信息后,发现了问题

    create trigger badQuaUpdate 
    after insert on TABLE_1 
    for each row        
    begin  
    declare c int;
    set c = (select C1-C2 from TABLE_1 where c1=new.c1);
    insert into TABLE_2(C1,C2) values (NEW.sumDatemm,c);
    end
    

    在这个出发其中where c1=new.c1出现了数据重复
    所以根据一开始百度的解决办法修改

    create trigger badQuaUpdate 
    after insert on TABLE_1 
    for each row        
    begin  
    declare c int;
    set c = (select C1-C2 from TABLE_1 where sumDatemm=new.sumDatemm);
    insert into TABLE_2(C1,C2) values (NEW.sumDatemm,c);
    end
    

    sumDatemm=new.sumDatemm中sumDatemm的值是唯一的
    修改触发器后,第一条记录顺利插入了
    感慨:度娘也不一定不靠谱,只是有时没有找到真正错误的位置
    参考文档:
    关于mysql错误:Subquery returns more than 1 row

    本文为博主原创文章,转载请附上博文链接!

    相关文章

      网友评论

        本文标题:spark-mysql:SQLException: Subque

        本文链接:https://www.haomeiwen.com/subject/pukcbqtx.html