我正面临锁定表溢出问题,下面是它显示的错误,一旦显示它就会崩溃代码。
锁定表溢出,在服务器上增加-L(915)
我已经检查了错误号,它说我们需要在服务器启动之前修改-L值,默认情况下它已设置为500。但我不认为除非我是公司的数据库管理员,否则我有权改变这个价值。 我试图做的是用大约11k个成员记录消除所有链接表记录(超过25个表链接到每个成员记录),同时将每个表备份到单独的文件中。因此粗略地在进入如下的成员循环时实现'EXCLUSIVE-LOCK',
for each member
EXCLUSIVE-LOCK:
/*
Then find each linked records in a order.
Extract them.
Delete them.
*/
Finally it extracts the member.
Delete member.
end.
当它遇到一定数量的成员记录时程序崩溃了。所以我不得不像批次一样运行它,
for each member
EXCLUSIVE-LOCK:
Increment a member count.
When count = 1k
then RETURN.
/*
Then find each linked records in a order.
Extract them.
Delete them.
*/
Finally it extracts the member.
Delete member.
end.
从字面上看,我最终运行了相同的代码超过11次以完成工作。我希望有人应该遇到这个问题,如果你想分享一个长期解决方案而不是我的临时解决方案,那将会很有帮助。
答案 0 :(得分:2)
您需要锁定每个作为交易一部分的记录。否则,其他用户可能会在您的事务提交之前进行相互冲突的更改。
在您的代码中,您有一个范围为外部FOR EACH的事务。因此,你需要为一个"成员"记录和与该成员关联的每个链接记录的另一个锁。
(由于您没有显示真实代码,因此您的实际代码也可能具有更广泛的事务范围......)
锁定表必须足够大以容纳所有这些锁定。锁定表也由所有用户共享 - 因此不仅必须保持锁定,而且还必须有其他人正在做的空间。
FWIW - 500非常非常低。默认值为8192.有两个启动参数使用字母" l",一个是大写,-L,这是锁表,它是服务器启动参数。小写字母-l是"本地缓冲区大小"那是一个客户参数。 (它控制可用于局部变量的内存量。)
"批处理",正如你已经完成的那样,是确保没有一个进程使用太多锁的典型方法。但是如果你的-L真的只有500,那么1000的批量大小是没有意义的。 100更典型。
更好的批处理方式:
define buffer delete_member for member.
define buffer delete_memberLink for memberLink. /* for clarity I'll just do a single linked table... */
for each member no-lock: /* do NOT get a lock */
batch_loop: do for delete_member, delete_memberLink while true transaction:
b = 0.
for each delete_memberLink exclusive-lock where delete_memberLink.id = member.id:
b = b + 1.
delete delete_memberLink.
if b >= 100 then next batch_loop.
end.
find delete_member exclusive-lock where recid( delete_member ) = recid( member ).
leave batch_loop. /* this will only happen if we did NOT execute the NEXT */
end.
end.
答案 1 :(得分:0)
您还可以增加-L数据库启动参数,以考虑一次性查询/删除。