来自 Oracle 的 Sqoop:"Snapshot too Old"

Sqoop from Oracle: "Snapshot too Old"

我正在设置一个自动化过程,使用以下命令从 oracle table sqoop 到 hdfs 目录:

sqoop-import --connect jdbc:oracle:thin:@redacted.company.com:1234/db --username redacted --password secret123 --num-mappers 1 --table table --target-dir /data/destination/directory/ --as-avrodatafile --compress --compression-codec org.apache.hadoop.io.compress.BZip2Codec

不幸的是,我收到以下错误消息:

Error:java.io.IOException: SQLException in nextKeyValue
    ...
Caused by: java.sql.SQLException: ORA-01555: snapshot too old: rollback segment number 336 with name "_SYSSMU336_879580159$" too small
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447)
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
    at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:951)
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:513)
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:227)
    at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:208)

我试图满足的业务需求是将整个 table 导入到我们的 hdfs 中。由于我们不拥有或管理此数据库,因此我无法控制 UNDO tablespace 和相关参数。工作安排在 运行 凌晨 1 点,这不是高峰时间,但由于自动化流程触及它,我无法说服人们在工作期间停止使用它。

我应该如何修改我的 sqoop-import 语句来避免这个错误?

这不是 Sqoop 问题。直接在 Oracle 上执行相同的语句会出现相同的错误。这是一个撤消 table 空间问题。您必须加快查询速度,或者必须增加 Oracle 撤消 table 空间大小。

可能的修复列表:

  • 在数据库较少时安排你的任务activity(甚至可能 要求人们暂时停止工作)。
  • 优化因该错误而失败的查询以读取更少的数据 并花费更少的时间增加 UNDO table 空间的大小。
  • 增加 UNDO_RETENTION 参数的大小。
  • 将 UNDO table空间设置为 GUARANTEE 模式。
  • 如果您要导出 table,请考虑使用 CONSISTENT=无参数。
  • 不要在游标循环内提交

问候 乔瓦

使用 --num-mappers=10(即增加并行度)足以解决此实例中的问题,而不会过多影响源代码。

此外,添加 --direct 参数将导致 Sqoop 使用 Oracle 特定的连接器,这将进一步加快速度,一旦我说服该数据库的 DBA 打开,就会将其添加到我的解决方案中必要的特权。 Direct 还支持选项 -Doraoop.import.consistent.read={true|false},它似乎反映了 Oracle 导出实用程序在函数中的 CONSISTENT 参数(注意,默认为 false),因为撤消表空间不会用于尝试保持一致性,消除在撤消表空间完全填满之前争先恐后地进行导入的需要。