Oracle“插入”命令的奇怪行为
Posted
技术标签:
【中文标题】Oracle“插入”命令的奇怪行为【英文标题】:The strange behaviour of the Oracle "insert into" command 【发布时间】:2020-09-01 09:12:55 【问题描述】:我正在观察“插入”命令中的奇怪情况。 我将尝试从我的角度解释情况 我的数据库中有 TEMP_LINKS 表,应用程序将数据插入其中。 假设查询位于 insert1.sql 中
insert into TEMP_LINK (ID, SIDE)
select ID, SIDE
from //inner query//
group by ID, SIDE;
commit;
并且有 java1 类执行它
...
executeSqlScript(getResource("path-to-query1"));
...
之后,另一个 java2 类再次插入到同一个 TEMP_LINK 表中
...
executeSqlScript(getResource("path-to-query2"));
...
query2 的样子
insert into TEMP_LINK (ID, SIDE)
select
ID, 'B'
from (
select ID
from ...tables
where ..conditions
minus (
select ID
from ..tables
union
select ID
from TEMP_LINKS
);
commit;
java1 和 java2 都在不同的线程中执行,java1 比 java2 更早完成。 但有时,第二次插入(来自 query2)根本不插入数据。我在日志中看到:更新计数 0,在 TEPM_LINKS 中只有来自 query1 的数据。 如果我再次运行应用程序,问题就消失了,两个查询都正确插入了数据。 早些时候我尝试将两个查询放入一个 sql 文件中,但问题也出现了。 所以,也许有人对我应该做什么有想法,因为我的已经结束了。一个有趣的事实 - sql“减号”操作仅使用一次 - 在该查询中2。
【问题讨论】:
您可以通过手动运行脚本来重现问题吗? java1 和 java2 在不同的威胁中执行,你说。但是一个接一个,或者它们可以并行执行?请记住,在提交之前,java1 上的数据对 java2 不可见。 当您从 java 执行时-您是否处理异常-您是否记录它们以查看问题所在?可能存在unique
约束违规或类似情况。
@Lini - 不,第二次运行给出正确的结果(两个查询都插入数据)
@Roberto Hernandez - 是的,它们在不同的线程中运行,但首先启动 java 1 并在 java2 之前完成
【参考方案1】:
Oracle 和 SQL Server 之间的一个很大区别是,Oracle 从不阻止读取。即使记录被锁定也是如此。下面是一个简化的解释。 Oracle 在事务开始时使用系统更改号 (SCN) 来确定该事务的数据库状态。各种事情都可能发生,插入、更新和删除,事务将数据库视为事务开始时的状态。更改仅在执行提交/回滚时很重要。
在您的情况下,如果第二个查询在第一个提交之前开始,则第二个查询不会看到第一个所做的任何更改,即使在第一次提交之后也是如此。您需要同步这些事务。最简单的方法是将它们组合成一个顺序执行。 Oracle 有很多更复杂的同步方法,在这种情况下我不会走那条路。
【讨论】:
以上是关于Oracle“插入”命令的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章
UICollectionView(插入和删除项目)的奇怪动画行为[关闭]