在使用 OceanBase 数据库进行批量数据导入时,
INSERT /*+ APPEND */旁路导入是提升大表加载性能的常用利器。但近期技术部门在将 OB 集群从 4.2.5 升级到 4.4.2后,同样的 SQL、同样的业务逻辑,低版本正常运行,升级后直接报错?今天就把解决方案一次性讲清楚!
批量通过PL复杂调用实现:INSERT /*+ APPEND/ INTO报错:
ORA-00600: internal error code, arguments: -4007, using full direct-insert within a transaction is not supported
OB V4.4.2
OB V4.2.5
使用同样的语法在OB V4.2.5就可以正常执行:
MySQL [test]> SET AUTOCOMMIT = 0; Query OK, 0 rows affected (0.01 sec) MySQL [test]> begin; Query OK, 0 rows affected (0.00 sec) MySQL [test]> INSERT /*+ APPEND */ INTO TEST_TARGET SELECT * FROM TEST_SOURCE; Query OK, 0 rows affected (0.07 sec) MySQL [test]> commit; Query OK, 0 rows affected (0.00 sec)
但是在升级为OB V4.4.2报错:
MySQL [test]> begin; Query OK, 0 rows affected (0.01 sec) MySQL [test]> INSERT /*+ APPEND */ INTO TEST_TARGET SELECT * FROM TEST_SOURCE; ERROR 1235 (0A000): using full direct-insert within a transaction is not supported MySQL [test]>
1.报错原因:
旁路导入属于 DDL 语句,无法在多行事务(包含多个操作的事务)中执行。
不能在 Begin 中执行。
using full direct-insert within a transaction is not supported
2.版本行为不一致原因:
1)在 OceanBase 数据库 V4.2.0 版本中,旁路导入功能必须与并行 DML 配合使用,如果未通过提示或会话开启并行 DML,则旁路导入的提示将被自动忽略。
2)如何验证: 通过explain extended查看执行计划,如果输出的信息中包含“direct-insert is enabled”,就说明该语句会走旁路,否则不走旁路
3)执行计划验证:
OB V4.2.5
1.通过hint开启并行dml EXPLAIN EXTENDED INSERT /*+ APPEND enable_parallel_dml parallel(4) */ INTO TEST_TARGET SELECT * FROM TEST_SOURCE; 输出摘要: Note: | | Degree of Parallelism is 4 because of hint | | Direct-mode is enabled in insert into select 2.不开启并行dml: EXPLAIN EXTENDED INSERT /*+ APPEND / INTO TEST_TARGET SELECT * FROM TEST_SOURCE; 执行计划输出摘要: Note: | | Degree of Parallelisim is 1 because of table property
OB V4.4.2
1.不开启并行DML: EXPLAIN EXTENDED INSERT /*+ APPEND / INTO TEST_TARGET SELECT * FROM TEST_SOURCE; Note: | | Degree of Parallelism is 16 because of session | | Direct-mode full is enabled in insert into select
综上所述,hint中加入旁路导入,不一定旁路导入就是生效的,需要通过执行计划进一步确认旁路导入是否生效
从 V4.3.4 版本开始引入,配置项
direct_load_allow_fallback,用于控制在指定旁路导入的导数操作中,如果遇到旁路导入不支持的场景时,导数操作是否回退为普通导入的方式。
ALTER SYSTEM SET direct_load_allow_fallback = 'true';
修改参数为true后,可规避代码中修改语法,旁路导入报错的问题,切换为普通导入模式。

如果你在实际操作中遇到问题,可以在评论区留言交流。后续我们会持续分享更多运维干货,记得 关注不迷路 ,下次见~
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70047467/viewspace-3117028/ ,如需转载,请注明出处,否则将追究法律责任。