Teradata 在存储过程中的多个语句期间锁定表

Teradata 在存储过程中的多个语句期间锁定表,teradata,Teradata,我希望通过Teradata事务实现与快照隔离等效的功能。Oracle支持这种类型的隔离,但Teradata不支持(至少在我所知道的14或更早版本中不支持)。目标是创建一个过程,删除表的内容,然后重新填充所有内容,同时防止其他用户读取/写入表 我遇到了beginrequest语句,根据我的理解,它允许优化器了解请求中的所有各种表锁 我编写了下面的过程,但不知道如何像在.NET应用程序中测试线程锁定那样轻松可靠地调试它(很容易设置断点和监视其他线程)。在Teradata中,不确定我在这里写的内容是否

我希望通过Teradata事务实现与快照隔离等效的功能。Oracle支持这种类型的隔离,但Teradata不支持(至少在我所知道的14或更早版本中不支持)。目标是创建一个过程,删除表的内容,然后重新填充所有内容,同时防止其他用户读取/写入表

我遇到了
beginrequest
语句,根据我的理解,它允许优化器了解请求中的所有各种表锁

我编写了下面的过程,但不知道如何像在.NET应用程序中测试线程锁定那样轻松可靠地调试它(很容易设置断点和监视其他线程)。在Teradata中,不确定我在这里写的内容是否会在整个过程中正确地以独占方式锁定
mydb.destinationtable
。这是正确的吗

编辑:我要补充一点,这个过程确实有效。它只是能够在SELECT执行删除/插入时正确计时

replace procedure mydb.myproc()
begin
    begin request

    locking mydb.destinationtable for exclusive
    delete mydb.destinationtable;

    locking mydb.destinationtable for exclusive
    insert into mydb.destinationtable
    select * from mydb.sourcetable;

    end request;
end;

开始请求
/
结束请求
创建所谓的多语句请求(MSR),该请求与使用F9在SQL Assistant中提交两个请求相同

要查看计划,请使用F9运行此命令:

EXPLAIN
locking mydb.destinationtable for exclusive
delete mydb.destinationtable;

insert into mydb.destinationtable
select * from mydb.sourcetable;
或在BTEQ中:

EXPLAIN
locking mydb.destinationtable for exclusive
delete mydb.destinationtable
;insert into mydb.destinationtable
select * from mydb.sourcetable;
顺便说一句,第二个锁是多余的

但是。当您将Delete&InsSel作为单个事务运行时,这两个事务都将被临时记录。这比单独的请求慢得多

更常见的方法是使用目标表的两个副本,并基于视图而不是表进行基本访问:

-- no BEGIN/END REQUEST
insert into mydb.destinationtable_2
select * from mydb.sourcetable;

-- there's just a short dictionary lock
-- all requests against the view submitted before the replace use the old data
-- and all submitted after the new data
replace view myview as 
select * from mydb.destinationtable_2;

delete from mydb.destinationtable_1;

现在,您的SP只需要在1和2之间切换逻辑(基于表[非]空)

1。使用视图而不是表来读取数据。2.加载时放置视图。3.加载完成后重新创建视图。据我所知,您还可以使用mload,它可以为您处理所有锁定。为什么不使用TASM来拒绝(或延迟)针对ETL期间加载的表(或数据库)的请求呢?这不是理想的解决方案,但解决了锁隔离问题。或者,您可以使用一个队列表和一个在视图中使用嵌套SELECT语句定义的列,最终用户访问该表,该表尝试访问队列表中的令牌。如果缺少令牌,查询将进入QT_延迟状态。@Robballer在研究TASM和查看队列表示例时,似乎涉及了很多设置和/或样板文件。不是说它们不起作用,而是我只是在寻找一种方法,在一个存储过程(即,不是BTEQ或类似的)中,1)在一个表上放置一个独占锁,2)执行多个语句(甚至不一定针对锁定的表),然后3)释放锁。dnoeth的回答似乎证实了我的操作代码将完全做到这一点,尽管暂时性日志记录可能会对性能造成影响,但我还不太了解。这只是一个关于如何调试行为的建议。创建一个假表,并在您的过程中插入此假表的更新,您通常会在其中设置断点。启动该过程之前,请从另一个会话锁定假表。这样,您的过程将在需要的地方阻塞,您可以测试锁定其他用户上的destinationtable的效果。@Insac我非常喜欢这个想法。如何无限期地锁定表?我确实希望避免交换表/视图。在存储过程的整个过程中,是否没有办法在表上放置独占锁?至于冗余锁,您是说仅在删除期间放置锁也会将锁应用于插入?至于临时日志记录,有没有一种方法既可以在同一事务下作为单独的语句运行,又可以在事务提交之前以独占方式锁定表?至于为什么我不想交换源,因为我想模拟Oracle的快照隔离。也许在幕后甲骨文也在做同样的事情,但这是隐含的。我不想在Teradata中手动模拟这种类型的隔离。当您执行MSR时,您在一个请求中将DEL&INS/SEL发送给优化器,因此优化器知道这两个语句访问同一个表,并应用最严格的锁。为什么您认为您需要快照隔离,它不是一个仓库吗?您正在处理什么类型的数据,以及多长时间运行一次该过程?继续使用术语“快照隔离”可能是一件坏事。在Oracle中,您可以在一个事务中运行多个查询。在提交更改之前,任何查询数据的人都将看到它在事务打开之前的状态,并且只有在提交更改时才能看到它。在我这里的例子中,如果有人在删除之后但在插入之前查询数据,他们的查询将返回0个结果。我想通过以独占方式锁定目标表来降低此风险,这样所有针对目标表的查询都必须等到锁释放后才能执行。它还负责所有的样板工作,包括交换视图、根据计数管理要使用的视图、确保在需要添加新列时所有加载表DDL都同步,基本上,我希望以独占方式锁定一个表,运行任意多个SQL语句(甚至不必在事务中),然后在完成后移除锁。