【问题标题】:Hadoop DBWritable : Unable to insert record to mysql from Hadoop reducerHadoop DBWritable:无法从 Hadoop 减速器向 mysql 插入记录
【发布时间】:2014-06-04 08:00:00
【问题描述】:

插入表格时遇到重复条目问题。

我已经使用Hadoop mapper从文件中读取记录。它成功地从文件中完全读取记录​​。但是当Hadoop reducer将记录写入mysql数据库时,出现以下错误。

java.io.IOException:键“PRIMARY”的重复条目“505975648”

但是 Mysql 表仍然是空的。无法从 Hadoop DBWritable reducer 将记录写入 mysql 表。

以下是错误日志:

警告:com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException:Connection.close() 已被调用。此状态下的无效操作。 在 sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 在 sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) 在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 在 java.lang.reflect.Constructor.newInstance(Constructor.java:526) 在 com.mysql.jdbc.Util.handleNewInstance(Util.java:406) 在 com.mysql.jdbc.Util.getInstance(Util.java:381) 在 com.mysql.jdbc.SQLError.createSQLException(SQLError.java:984) 在 com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956) 在 com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926) 在 com.mysql.jdbc.ConnectionImpl.getMutex(ConnectionImpl.java:3018) 在 com.mysql.jdbc.ConnectionImpl.rollback(ConnectionImpl.java:4564) 在 org.apache.hadoop.mapred.lib.db.DBOutputFormat$DBRecordWriter.close(DBOutputFormat.java:72) 在 org.apache.hadoop.mapred.ReduceTask$OldTrackingRecordWriter.close(ReduceTask.java:467) 在 org.apache.hadoop.mapred.ReduceTask.runOldReducer(ReduceTask.java:539) 在 org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:421) 在 org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:262)

2014 年 6 月 4 日下午 1:23:36 org.apache.hadoop.mapred.LocalJobRunner$Job 运行 警告:job_local_0001 java.io.IOException: 重复项 '505975648' 键 'PRIMARY' 在 org.apache.hadoop.mapred.lib.db.DBOutputFormat$DBRecordWriter.close(DBOutputFormat.java:77) 在 org.apache.hadoop.mapred.ReduceTask$OldTrackingRecordWriter.close(ReduceTask.java:467) 在 org.apache.hadoop.mapred.ReduceTask.runOldReducer(ReduceTask.java:531) 在 org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:421) 在 org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:262)

【问题讨论】:

    标签: hadoop mysql-error-1064 hadoop-streaming hadoop-plugins


    【解决方案1】:

    DBOutputFormat / DBRecordWriter 在数据库事务中执行所有操作。虽然您现在表中可能没有任何内容,但如果您尝试使用相同的主键在同一个事务中执行两次插入,您将收到此错误,这就是正在发生的事情。为了更好地跟踪这一点,您可以添加日志记录。您可以通过获取 DBOutputFormat 的代码并创建一个新的类似名称的类来做到这一点。我叫我的 LoggingDBOutputFormat。更新您的工作代码以改用这种新的输出格式。对于新的输出格式,您可以更改 close 方法以在执行语句之前记录它们:

        /** {@inheritDoc} */
    public void close(TaskAttemptContext context) throws IOException {
      try {
          LOG.warn("Executing statement:" + statement);   
    
          statement.executeBatch();
        connection.commit();
      } catch (SQLException e) {
        try {
          connection.rollback();
        }
        catch (SQLException ex) {
          LOG.warn(StringUtils.stringifyException(ex));
        }
        throw new IOException(e.getMessage());
      } finally {
        try {
          statement.close();
          connection.close();
        }
        catch (SQLException ex) {
          throw new IOException(ex.getMessage());
        }
      }
    }
    

    然后您可以检查 mysql 端的常规日志以查看是否执行了任何操作。很可能您会看到您的事务因错误而被回滚。要解决此问题,请确保主键是唯一的。如果更新/更新插入是您想要的,您可以制作一个输出/记录写入器来执行此操作,但这是一项不同的工作。

    【讨论】:

      猜你喜欢
      • 2017-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-21
      • 2016-07-02
      • 2016-08-13
      相关资源
      最近更新 更多