本文主要描述在外键约束 DISABLE/ENABLE 的情况下,执行 DROP TABLE 和 TRUNCATE TABLE 命令的不同行为表现。
跟原生 MySQL 一样,OceanBase 数据库中的外键检查由 foreign_key_checks 变量控制,该变量默认启用。详细使用说明可参见:foreign_key_checks。基于兼容性的考量,从 OceanBase 数据库 V4.2.1 BP2 版本开始废弃 Oracle 模式下 foreign_key_checks 租户变量。即 foreign_key_checks 变为 MySQL Only,Oracle 模式上可以设置,但即使设置为 0 也一直是 ON 的,无法关闭。OceanBase 数据库 Oracle 模式下建议客户使用 Oracle 兼容的表级外键约束控制。


详细说明
在 Oracle 模式中创建外键约束,并对其进行禁用和启用,以及在 禁用/启用 外键约束的情况下执行 DROP/TRUNCATE 父表的操作,演示示例如下。
-- 建父表。
obclient [SYS]> CREATE TABLE test_foreignkey_parent (c1 INT PRIMARY KEY);
Query OK, 0 rows affected (0.197 sec)
-- 建子表。
obclient [SYS]> CREATE TABLE test_foreignkey_child (
c1 INT PRIMARY KEY,
FOREIGN KEY (c1) REFERENCES test_foreignkey_parent (c1)
);
Query OK, 0 rows affected (0.230 sec)
-- 查询约束。
obclient [SYS]> SELECT TABLE_NAME,CONSTRAINT_NAME,STATUS FROM USER_CONSTRAINTS WHERE CONSTRAINT_TYPE ='R' ORDER BY TABLE_NAME DESC;
+-----------------------+---------------------------------------------+---------+
| TABLE_NAME | CONSTRAINT_NAME | STATUS |
+-----------------------+---------------------------------------------+---------+
| TEST_FOREIGNKEY_CHILD | TEST_FOREIGNKEY_CHILD_OBFK_1732700298094827 | ENABLED |
+-----------------------+---------------------------------------------+---------+
1 row in set (0.215 sec)
-- 禁用约束。
obclient [SYS]> ALTER TABLE test_foreignkey_child DISABLE CONSTRAINT TEST_FOREIGNKEY_CHILD_OBFK_1732700298094827;
Query OK, 0 rows affected (0.256 sec)
-- 查询约束。
obclient [SYS]> SELECT TABLE_NAME,CONSTRAINT_NAME,STATUS FROM USER_CONSTRAINTS WHERE CONSTRAINT_TYPE ='R' ORDER BY TABLE_NAME DESC;
+-----------------------+---------------------------------------------+----------+
| TABLE_NAME | CONSTRAINT_NAME | STATUS |
+-----------------------+---------------------------------------------+----------+
| TEST_FOREIGNKEY_CHILD | TEST_FOREIGNKEY_CHILD_OBFK_1732700298094827 | DISABLED |
+-----------------------+---------------------------------------------+----------+
1 row in set (0.009 sec)
-- 清理表数据,禁用约束后是可以清理的。
-- OceanBase 数据库 V4.1.x 版本中的 TRUNCATE TABLE 不是先 DROP TABLE 然后再 CREATE TABLE 了,而是改成了创建一个新的 TABLET ,然后将旧的 TABLET 和新的 TABLET 交换一下。
-- 因此,从 OceanBase 数据库 V4.1.0 版本开始,TRUNCATE TABLE 后该表的 TABLE_ID 保持不变,该表所在的 Leader 也保持不变。
obclient [SYS]> TRUNCATE TABLE test_foreignkey_parent;
Query OK, 0 rows affected (0.184 sec)
-- 删除表失败,这里是因为有子表依赖故而无法删除。
obclient [SYS]> DROP TABLE test_foreignkey_parent;
ORA-02449: unique/primary keys in table referenced by foreign keys
-- 启用约束。
obclient [SYS]> ALTER TABLE test_foreignkey_child ENABLE CONSTRAINT TEST_FOREIGNKEY_CHILD_OBFK_1732700298094827;
Query OK, 0 rows affected (0.730 sec)
-- 查询约束。
obclient [SYS]> SELECT TABLE_NAME,CONSTRAINT_NAME,STATUS FROM USER_CONSTRAINTS WHERE CONSTRAINT_TYPE ='R' ORDER BY TABLE_NAME DESC;
+-----------------------+---------------------------------------------+---------+
| TABLE_NAME | CONSTRAINT_NAME | STATUS |
+-----------------------+---------------------------------------------+---------+
| TEST_FOREIGNKEY_CHILD | TEST_FOREIGNKEY_CHILD_OBFK_1732700298094827 | ENABLED |
+-----------------------+---------------------------------------------+---------+
1 row in set (0.011 sec)
-- 清理表数据,启用外键约束后数据清理失败。
-- 无法清理有外键约束的父表。
obclient [SYS]> TRUNCATE TABLE test_foreignkey_parent;
ORA-00600: internal error code, arguments: -5594, Cannot truncate a table referenced in a foreign key constraint (TEST0925.TEST_FOREIGNKEY_CHILD, CONSTRAINT TEST_FOREIGNKEY_CHILD_OBFK_1732700298094827 FOREIGN KEY ("C1") REFERENCES TEST0925.TEST_FOREIGNKEY_PARENT ("C1"))
obclient(TEST0925@perforacle)[TEST0925]>
-- 删除表,这里因为有子表依赖故而无法删除。
obclient [SYS]> DROP TABLE test_foreignkey_parent;
ORA-02449: unique/primary keys in table referenced by foreign keys
结论
- 使用 Oracle 兼容的表级外键约束控制,
DISABLE子表上的外键约束,则TRUNCATE TABLE父表可以成功;ENABLE子表上的外键约束,则TRUNCATE TABLE失败,报错ORA-00600: internal error code, arguments: -5594, Cannot truncate a table referenced in a foreign key constraint。 - 不管是否对子表外键约束
DISABLE,DROP TABLE都无法成功,报错ORA-02449: unique/primary keys in table referenced by foreign keys。
影响租户
影响 OceanBase 数据库中的 Oracle 租户,对于 SYS 租户和 MySQL 租户无影响。
适用版本
OceanBase 数据库 V4.x 版本。