使用“锁定”截断/填充从 Oracle 中的视图填充表

Posted

技术标签:

【中文标题】使用“锁定”截断/填充从 Oracle 中的视图填充表【英文标题】:Populating a table from a view in Oracle with "locked" truncate/populate 【发布时间】:2014-05-06 20:23:25 【问题描述】:

我想按计划从(可能很大的)视图中填充表格。

我的流程是:

禁用表索引 截断表 将数据从视图复制到表 对表启用索引

在 SQL Server 中,我可以将进程包装在事务中,这样当我截断表时,架构修改锁将一直保持到我提交为止。这实际上意味着在整个过程完成之前,没有其他进程可以插入/更新/任何内容。

但我知道,在 Oracle 中,截断表语句被视为 DDL,因此会发出隐式提交。

所以我的问题是如何在这里模仿 SQL Server 的行为?我不希望任何其他进程在截断和(重新)填充表时尝试插入/更新/任何内容。我也希望我的其他进程不知道任何锁。

提前致谢。

【问题讨论】:

您可以删除而不是截断,但这会产生更多的重做并花费更长的时间,锁定表的时间更长 - 正如您似乎意识到的那样。我想知道您是否可能想要一个物化视图而不是表格,并按计划刷新?这符合您想要实现的目标吗? 感谢您的评论。正如我(巧妙地)在我的问题中提到的那样,我有另一个进程将写入表/物化视图。我可以在 Oracle 中写入物化视图吗?如果是这样,当两个进程同时运行时,我是否会免受唯一约束违规的影响?再次感谢。 不,我想我假设您的意思是您想停止对源视图/表的更新。如果要删除并重新填充目标表,为什么要允许更新目标表?这些手动更新每次都会丢失? 我承认这是一个奇怪的要求。一些数据需要“尽可能实时”,这意味着我想在我的应用程序中持久保存实体时将单独的行写入表中(不是严格在同一个事务中,而是在队列中异步)。计划的重新填充将处理对外键引用表的更改(实际上它将处理所有行)。如果我能把它拉出来,就会产生这样的错觉,即数据不是实时的。我希望这是有道理的。 【参考方案1】:

使您的表成为仅具有单个分区和本地索引的分区表。然后每当您需要刷新时:

将视图中的数据复制到新的临时表中

CREATE TABLE tmp AS SELECT ... FROM some_view;

用临时表交换分区:

ALTER TABLE some_table
EXCHANGE PARTITION part WITH TABLE tmp
WITHOUT VALIDATION;

该表仅在分区交换期间锁定,无需验证和全局索引更新,应该是即时的。

【讨论】:

感谢您的回答。想必这里的想法是获取表的排他锁,将数据复制到临时表,然后与临时表交换表。我唯一担心的是,即使即时,隐式提交也会在 ALTER TABLE EXCHANGE PARTITION 之前发生,可能允许另一个进程写入表......也就是说,我不完全确定这种情况发生的可能性或这样做的后果是否会很糟糕。我目前也不确定是否要进行暂存/交换表方案。再次感谢。

以上是关于使用“锁定”截断/填充从 Oracle 中的视图填充表的主要内容,如果未能解决你的问题,请参考以下文章

从 Popover 中显示的 TableView 中的单元格填充 textField

调整SQL Server中的大型查询

oracle中lpad函数是干嘛用的?

TextLabel 在 ScrollView 中被截断

List View(列表视图)

List View(列表视图)