Database 在PostgreSQL 9.2中更新数据库行而不锁定表
尝试使用PostgreSQL 9.2在表上运行类似的update语句:Database 在PostgreSQL 9.2中更新数据库行而不锁定表,database,postgresql,cursor,sql-update,Database,Postgresql,Cursor,Sql Update,尝试使用PostgreSQL 9.2在表上运行类似的update语句: UPDATE table SET a_col = array[col]; 我们需要能够在~10M行的表上运行此操作,并且不让它锁定表(因此在更新运行时仍然可以执行正常操作)。我相信使用游标可能是正确的解决方案,但我真的不知道它是否正确,也不知道应该如何使用游标来实现它 我已经想出了这个光标代码,我认为这可能是好的 编辑:添加光标功能 CREATE OR REPLACE FUNCTION update_fields(
UPDATE table
SET a_col = array[col];
我们需要能够在~10M行的表上运行此操作,并且不让它锁定表(因此在更新运行时仍然可以执行正常操作)。我相信使用游标可能是正确的解决方案,但我真的不知道它是否正确,也不知道应该如何使用游标来实现它
我已经想出了这个光标代码,我认为这可能是好的
编辑:添加光标功能
CREATE OR REPLACE FUNCTION update_fields() RETURNS VOID AS $$
DECLARE
cursor CURSOR FOR SELECT * FROM table ORDER BY id FOR UPDATE;
BEGIN
FOR row IN cursor LOOP
UPDATE table SET
a_col = array[col],
a_col2= array[col2]
WHERE CURRENT OF cursor;
END LOOP;
END;
$$ LANGUAGE plpgsql;
创建或替换函数update_fields()返回VOID作为$$
声明
光标用于按id从表顺序中选择*进行更新;
开始
对于游标循环中的行
更新表集
a_col=数组[col],
a_col2=数组[col2]
其中光标的当前位置;
端环;
结束;
$$语言plpgsql;
MVCC
首先,如果“正常操作”包括SELECT
查询,则将自动处理<代码>更新不会阻止选择
,反之亦然SELECT
只查看提交的数据(或在同一事务中执行的操作),因此大型UPDATE
的结果在完成(提交)之前对其他事务不可见
性能/膨胀
如果没有其他对象引用该表,而且您没有并发写入操作(这将丢失!),
您还可以在桌面上提供非常短的独占锁,
当然,您还有额外的磁盘空间:
通过在后台创建表的更新版本,可以将锁定保持在最低限度。确保它的所有内容都是插入式替换,然后删除原始内容并重命名副本
CREATE TABLE tbl_new (LIKE tbl_org INCLUDING CONSTRAINTS);
INSERT INTO tbl_new
SELECT col_a, col_b, array[col] aS col_c
FROM tbl_org;
我正在使用创建表(比如..包括约束)
,因为():
NOTNULL约束总是复制到新表中<代码>检查
仅当指定了包含约束的时,才会复制约束;
其他类型的约束将永远不会被复制
确保新桌子准备好了。然后:
DROP tbl_org;
ALTER TABLE tbl_new RENAME TO tbl_org;
结果在很短的时间窗口内,表被独占锁定
这实际上只是关于性能。它可以相当快地创建一个没有任何膨胀的新表。如果您有外键或视图,您仍然可以这样做,但是您必须准备一个脚本来删除并重新创建这些对象,这可能会创建额外的独占锁
并发写入
对于并发写操作,实际上您所能做的就是将更新分块。您不能在单个事务中这样做,因为锁只在事务结束时释放
您可以使用,它可以在另一个数据库(包括自身)上启动独立事务。通过这种方式,您可以在一个do
语句或带有循环的plpgsql函数中完成所有操作。下面是一个松散相关的答案,其中包含有关dblink的更多信息:
使用游标的方法
函数中的光标不会为您购买任何东西。任何函数都自动包含在事务中,所有锁仅在事务结束时释放。
即使您使用了(您不使用),它也只会释放一些资源,而不会释放表上获取的锁。我引述该手册:
CLOSE
关闭打开光标下的门户。这可以用来
在事务结束之前释放资源,或释放
要再次打开的游标变量
您需要运行单独的事务或(ab)使用哪个选项来运行该事务。是否有其他对象引用该表,如视图的外键?@ErwinBrandstetter没有,根本没有外键。非常感谢您的回答。“正常操作”还包括update语句。我想用光标(请看我更新的问题)来做这件事,但我不确定这是否是个好主意。@Juancarlosto:恐怕,光标不是个好主意。我在回答中加了一点。