截断行并插入新行而不引入服务中断?

问题描述:

我在PostgreSQL 9.5数据库表中有大约1,500,000条记录,并且我得到一个CSV文件(通过http post请求),其中包含新的〜1,500,000行,其中一些没有改变,有些不同,有些被删除到原始行。截断行并插入新行而不引入服务中断?

我再

  1. 截断旧表
  2. 循环遍历CSV文件的行
  3. 将每个行插入表

我需要的是一个办法做到这一点没有向我的客户介绍服务中断,即服务应该继续使用旧数据,直到完成所有三个步骤。目前服务暂停将会持续1个小时,这就是读取CSV并插入所有新行所需的时间。如果需要的话,我可以休息5分钟。

我该如何实现这样的行为?

这里是我的Python脚本的简化版本:

cursor = conn.cursor(cursor_factory=DictCursor) 
cursor.execute('TRUNCATE TABLE rows CASCADE') 
with open(request.files.csv) as csv_file: 
    for line in csv_file: 
     row = parse_line(line) 
     cursor.execute(
      '''INSERT INTO rows (name, bla, blu) 
      VALUES (%(name)s, %(bla)s, %(blu)s)''', 
      row, 
     ) 
cursor.commit() 

  1. 使用COPY代替with open(request.files.csv),因为150万行从CSV
  2. 复制到一个表在几秒钟内,如果这些秒(让我们假设一个分钟)太长,只是使用交易无济于事,导致表格上的truncate requires lock,而不是行

TRUNCATE上

所以它的运作 每个表获取到一个ACCESS EXCLUSIVE锁,如果你可以重建在桌子上,兴田最重要依赖对象很可能是:

create t_table as select * from "rows" where false; 
copy t_table from request.files.csv; 
--build all needed dependant objects (indexes, constraints,triggers); 
begin; 
    alter table "rows" rename to "some_name"; 
    alter table "t_table " rename to "rows"; 
end; 
--here is a miliseconds glitch to swith for users (if you use memcache or so - need to refresh it) 
drop table "some_name"; 

更新 to copy columns from csv to several table columns list columns

COPY table_name [(column_name [,...])]]

+0

截断会在truncate命令出现问题之前影响其他正在处理快照的事务,所以它不适合'服务应该继续使用旧数据,直到完成所有三个步骤完成要求。 –

+0

这看起来很棒,谢谢!只有一个跟进问题; CSV文件有20列,但我的表只需要其中的五个。我能否以某种方式只复制五个特定的列,或者我应该在将Python转发到数据库之前使用Python编辑CSV? –

+1

@MarkusMeskanen更新。使用request.files.csv中的'copy t_table(col1,col4,col5等);' –