这总是棘手的任务。事务的大小(例如为了安全回滚)受事务日志大小的限制。事务日志不仅由您的 sql 命令填充,还由同时使用 db 的其他用户的命令填充。
我建议使用以下方法之一/或组合
1. 提交
经常提交 - 在你的情况下,我会在每个删除命令之后提交一次
2.增加事务日志的大小
我记得默认的 db2 事务日志不是很大。事务日志的大小应该为每个数据库单独计算/调整。在此处参考,并在此处提供更多详细信息
3. 存储过程
编写和调用在块中删除的存储过程,例如:
-- USAGE - create: db2 -td@ -vf del_blocks.sql
-- USAGE - call: db2 "call DEL_BLOCKS(4, ?)"
drop PROCEDURE DEL_BLOCKS@
CREATE PROCEDURE DEL_BLOCKS(IN PK_FROM INTEGER, IN PK_TO INTEGER)
LANGUAGE SQL
BEGIN
declare v_CNT_BLOCK bigint;
set v_CNT_BLOCK = 0;
FOR r_cur as c_cur cursor with hold for
select tableky from tablename
where tableky between pk_from and pk_to
for read only
DO
delete from tablename where tableky=r_cur.tableky;
set v_CNT_BLOCK=v_CNT_BLOCK+1;
if v_CNT_BLOCK >= 5000 then
set v_CNT_BLOCK = 0;
commit;
end if;
END FOR;
commit;
END@
4.导出+导入替换选项
在某些情况下,当我需要清除非常大的表或只留下少量记录(并且没有 FK 约束)时,我使用了导出 + 导入(替换)。替换导入选项非常具有破坏性——它会在开始导入新记录之前清除整个表(参考db2 import 命令),因此请确保您在做什么并在之前进行备份。对于此类敏感操作,我创建了 3 个脚本并分别运行:备份、导出、导入。这是导出的脚本:
echo '===================== export started ';
values current time;
export to tablename.del of del
select * from tablename where (tableky between 1 and 1000
or tableky between 2000 and 3000
or tableky between 5000 and 7000
) ;
echo '===================== export finished ';
values current time;
这是导入脚本:
echo '===================== import started ';
values current time;
import from tablename.del of del allow write access commitcount 2000
-- !!!! this is IMPORTANT and VERY VERY destructive option
replace
into tablename ;
echo '===================== import finished ';
5.截断命令
Db2 在 9.7 版中引入了 TRUNCATE 语句,它:
从表中删除所有行。
基本上:
TRUNCATE TABLE <tablename> IMMEDIATE
我在 db2 中没有使用 TRUNCATE 的经验,但在其他一些引擎中,该命令非常快并且不使用事务日志(至少不是以通常的方式)。请在此处或官方文档中查看所有详细信息。作为解决方案 4,此方法也非常具有破坏性 - 它会清除整个表,因此在发出命令之前要非常小心。确保先执行表/数据库备份的先前状态。
请注意何时执行此操作
当 db 上没有其他用户时,或通过锁定表来确保这一点。
回滚注意事项
在事务 db(如 db2)中,回滚可以将 db 状态恢复到事务开始时的状态。在方法 1,3 和 4 中,这是无法实现的,因此如果您需要“恢复到原始状态”的功能,唯一可以确保这一点的选项是方法 nr。2-增加事务日志。