2015-11-06 21 views
3

我正计划在我的巨大表(超过十亿行)上执行长时间运行的更新。此更新将按固定数字乘以一列的值。PL/SQL - 不更新已更改的行

问题是,在我的更新(可能会持续几个小时)期间,肯定会有短事务更新某些行,并且这些行将具有不应更新的正确值,尽管它们仍会满足我的更新条件。

所以,问题是 - 我怎么跳过(不更新)这是我的长时间运行更新的事务之外更新行?

+0

让我们假设在您运行长交易时短交易不会来。但是,在开始长交易之前,存在一些已经运行并更新了一些行的短交易。所以,这些行将是正确的。你怎么知道跳过它们? (我想说的是,你的问题没有什么事务大小或并发性,但数据质量和一致性) –

回答

0

哦,我完全忘了这个问题。 因此,我最终通过将其副本保存到另一个表(我不得不更新那些满足给定条件的行)来制作当前行的快照。之后,我更新了未更改其值的行(使用合并)。

4

一种方法是使用FOR UPDATE SKIP LOCKED,这样其他会话将无法挑选已被选中更新的行。

例如,

会议1:

SQL> SELECT empno, deptno 
    2 FROM emp WHERE 
    3 deptno = 10 
    4 FOR UPDATE NOWAIT; 

    EMPNO  DEPTNO 
---------- ---------- 
     7782   10 
     7839   10 
     7934   10 

SQL> 

会话2:

SQL> SELECT empno, deptno 
    2 FROM emp WHERE 
    3 deptno in (10, 20) 
    4 FOR UPDATE NOWAIT; 
    FROM emp WHERE 
     * 
ERROR at line 2: 
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired 

现在让我们跳过其通过会话1

锁定的行
SQL> SELECT empno, deptno 
    2 FROM emp WHERE 
    3 deptno IN (10, 20) 
    4 FOR UPDATE SKIP LOCKED; 

    EMPNO  DEPTNO 
---------- ---------- 
     7369   20 
     7566   20 
     7788   20 
     7876   20 
     7902   20 

SQL> 

所以,部门= 10是由会话1,然后锁定部门= 20由会话2

+0

这就是所谓的pessimstic锁? – Moudiz

+1

@Moudiz是的,悲观的锁定在有状态的环境。 –

+0

但是,如果会话1在会话2之后运行,则这不起作用,对吗? –

1

我已经做了一些你的问题锁定,但我的表是不是过于庞大喜欢你。

我重新设计了我的表格,添加了2列。

created_date:插入数据时触发器将sysdate放入。

modified_date:更新数据时触发器将sysdate放入。

然后我可以在我的where子句中使用created_date或modified_date。

例子:

UPDATE TABLE table_name 
SET column_name = 'values' 
WHERE created_date < SYSDATE; 

我希望这会帮助你。

+0

这是我的第一个想法,但不幸的是,修改表结构不是一个选项。 –