我正在尝试编写一个脚本,由没有真正了解pl / sql的客户执行,
我在PL / sql中做了很多事务来清理它们的格局,然后必须添加一些约束来防止这种情况再次发生,我在清理后自动提交,并希望通过添加完成我的PL块这些约束
唯一的问题是我无法保证在尝试向它们添加约束时不会锁定表,是否在oracle中等待解锁类型的命令?
谢谢你,对oracle的新手,似乎无法找到这个,我已经梳理了一些API,但我在时间敏感点,并且证明很难找到,当我认为它似乎是一个漂亮DB管理的常规问题
答案 0 :(得分:4)
,你应该通过execute immedaite调用:
LOCK TABLE <table_name> IN EXCLUSIVE MODE WAIT <n>;
其中是等待的秒数。
但请记住,即使你在第一个ddl之后锁定它也会被释放,因为DDL会自动提交。因此,无法保证DDL命令列表将像在一个事务中一样逐个执行。
答案 1 :(得分:3)
命令是:
LOCK TABLE tab IN EXCLUSIVE MODE;
如果有另一个具有类似锁定的会话(不应该存在),这将无限期地等待。
您可以在DDL之前显式锁定表(使用“WAIT”),但如果您担心另一个会话持有独占锁,则不一定能解决所有问题。听起来更像是由于另一个会话中的DML事务而遇到ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
。这最终会完成,因此在ALTER TABLE
之前发出上述锁定命令将对您有所帮助。请注意,如果其他地方有一个挂起的会话,LOCK TABLE命令可以无限期地等待,除非你设置了超时。
让我们举个例子:
在会话A中,我在tab
SQL> INSERT INTO tab VALUES(...);
在会话B中,我尝试向表中添加约束。
SQL> alter table tab add constraint uk_name unique(name);
alter table tab add constraint uk_name unique(name)
*
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expire
所以我得再试一次。但是,如果您在DDL之前使用LOCK ... EXCLUSIVE(WAIT)
SQL> lock table tab in exclusive mode;
-- indefinite period while the session A transaction blocks session B
然后会话A提交或回滚
SQL> commit;
当我们看到锁定命令返回Table(s) locked
Table(s) Locked.
SQL> alter table tab add constraint uk_name unique(name);
Table altered. (**comment Lock is released by the implicit commit issued the DDL statement)
SQL>
由于DDL语句释放锁,因此每个DDL都需要以新的LOCK语句开头。如果你想使用它,我建议添加一个超时(正如Justin的评论中所建议的那样)。让我们在放弃之前等待一分钟。
SQL> lock table tab in exclusive mode WAIT 60;
虽然如果这是一个繁忙的数据库上的无人参与的脚本,我可能会用超过60秒的时间。只需将所有内容记录到假脱机文件中,稍后检查日志是否有错误。
除此类维护之外的任何内容可能都要求您先停顿数据库,否则只需根据具体情况处理争用。