我计划在我庞大的桌子上进行长时间更新(超过十亿行)。此更新会将一列的值乘以固定数字。
问题在于,在我的更新期间(可能持续几个小时)肯定会有更新某些行的短事务,并且这些行将具有不应更新的正确值,尽管它们仍将满足我的更新'条件。
所以问题是 - 如何跳过(不更新)在我长时间运行的更新事务之外更新的行?
答案 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锁定。
答案 1 :(得分: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;
我希望这会对你有所帮助。
答案 2 :(得分:0)
哦,我完全忘记了这个问题。 因此,我最终通过将副本保存到另一个表来创建当前行的快照(我只需要更新那些满足给定条件的行)。之后,我更新了尚未更改其值的行(使用合并)。