请参阅我以前的帖子。
Sql Cleanup script, delete from one table that's not in the other 1
使用DB2 for IBM i(As400,Db2)。
我正在执行以下sql作为清理脚本凌晨3点。
DELETE FROM p6prodpf A WHERE (0 = (SELECT COUNT(*) FROM P6OPIPF B WHERE B.OPIID = A.OPIID))
我有一个不同的进程,在此sql运行的同时插入两条记录,第一条记录是P6OPIPF
记录,然后将详细记录插入P6PRODPF
。
问题所在。
运行SQL清理后,P6PRODPF
记录丢失。但请记住,存储记录的过程同时进行。
我如何理解SQL是通过P6PRODPF
并检查记录是否在P6OPIPF
中,如果它不在P6OPIPF
中,则删除P6PRODPF
。
但是后来我在这个SQL上的I系统导航器中运行了Visual Explain,得到了以下结果。
现在我很困惑。
在Visual解释之后看起来语句以检查P6OPIPF
开始。
然后它会显示:如果P6OPIPF
中的时间实例中有记录,而P6PRODPF
中没有相同键的记录,则删除P6PRODPF
。
这可以解释我的插入记录和sql脚本的进程同时运行时P6PRODPF
被删除的问题。
所以我如何在序列中看到它。(我的理论)
开始插入两条记录的过程。
插入两条记录的过程会插入第一条记录
P6OPIPF
。
P6OPIPF
记录并检查它是否有P6PRODPF
条记录。在这个阶段
仍然没有插入P6PRODPF
,所以Sql认为它需要
删除P6PRODPF
。P6PRODPF
中的第二条记录。P6PRODPF
删除P6PRODPF
中新插入的记录,留下P6OPIPF
记录没有P6PRODPF
记录。我说错了吗?
我真正想知道的只是上面列出的删除脚本。我如何理解SQL是通过P6PRODPF来检查记录是否在P6OPIPF中,如果它不在P6OPIPF中则删除P6PRODPF。但在视觉解释之后,我可以看到它的开始与检查P6OPIPF。那么删除语句首先检查什么?
插入代码在CA PLEX生成器中生成。 RPGIV代码。
我的一个函数将首先插入P6OPIPF
(OperationsItem.Update.InsertRow),然后在P6PRODPF
(ProductDetail.Update.InsertRow)中插入其详细信息。
将执行删除脚本的我的预定功能代码。
Scheduled delete script function
希望它有意义。
答案 0 :(得分:2)
Visual Explain是了解DB正在做什么的有用工具,特别是在尝试提高性能时。
但SQL不是一种过程语言。当你运行这个语句时,你不应该也不能试着说,数据库正在这样做,然后就是这样做。
虽然对于该特定运行可能是真的,但它高度依赖于可用的数据和资源。您无法围绕所看到的步骤对流程进行编码。
你真的不应该试图同时运行这两个进程,根本没有办法确保你最终会得到什么;至少在使用默认隔离级别时(可能是“no commit”或“read uncommited”,具体取决于接口。)
如果您必须同时运行这两个进程,您可能希望在“可重复读取”或“可序列化”下运行删除;这应该具有锁定被引用的表的效果,以便其他进程不能更改它们。
或者,您可以在读稳定性或更高的隔离级别下运行删除和插入。
答案 1 :(得分:2)
为了解释Visual Explain,DB2将在执行DELETE子句之前检查内部表达式 - 它必须,否则它不知道哪些行受到影响。
归档行未归档的原因是删除脚本在插入脚本之前运行。
答案 2 :(得分:1)
您是否听说过“交易”和“隔离”的概念?通常,针对同一数据库运行的不同进程相互屏蔽(隔离),因此它们在运行时不会看到同时运行的任何其他事务的直接影响。逻辑上,两个事务(一个SQL语句的过程或序列)以串行方式执行。
在您的情况下,第一个过程是“第一个”或“第二个”。如果您重复测试,您可能会看到不同的结果,具体取决于谁是“第一”(逻辑上)。