如何在python连接对象中发生异常之前提交所有挂起的查询

时间:2012-12-12 10:58:27

标签: python postgresql transactions commit psycopg2

我在python中使用psycopg2,但我的问题是DBMS不可知(只要DBMS支持事务):

我正在编写一个将记录插入数据库表的python程序。要插入的记录数量超过一百万。当我编写代码以便它在每个insert语句上运行一个提交时,我的程序太慢了。因此,我改变了我的代码,每5000条记录运行一次提交,速度差异很大。

我的问题是,在某些时候插入记录时会发生异常(某些完整性检查失败)并且我希望将更改提交到那一点,除了当然对于导致的最后一个命令发生异常,并继续使用其余的插入语句。

我还没有找到实现这个目标的方法;我唯一能做到的就是捕获异常,回滚我的事务并继续从那一点开始,我放弃了我的挂起的insert语句。此外,我尝试(深入)复制光标对象和连接对象,但也没有任何运气。

有没有办法直接或间接地实现此功能,而无需回滚和重新创建/重新运行我的语句?

提前谢谢大家,

乔治。

2 个答案:

答案 0 :(得分:3)

我怀疑你会找到一种快速的跨数据库方式来做到这一点。您只需优化批量大小的速度增益与条目导致批次失败时重复工作的速度成本之间的平衡。

有些DB可以在发生错误后继续执行事务,但PostgreSQL不能。但是,它允许您使用SAVEPOINT命令创建子事务。这些远非免费,但它们的成本低于完整交易。所以你可以做的就是每行(例如)100行,发出SAVEPOINT然后释放先前的保存点。如果您遇到错误ROLLBACK TO SAVEPOINT,请提交,然后选择上次停止的地方。

答案 1 :(得分:2)

如果您在每5000个记录间隔后提交事务,似乎您可以对输入数据进行一些预处理,并实际将其分解为5000个记录块的列表,即[[[row1_data],[row2_data]...[row4999_data]],[[row5000_data],[row5001_data],...],[[....[row1000000_data]]] < / p>

然后运行插入,并跟踪您正在处理的块以及当前正在插入的记录。当您收到错误时,重新运行该块,但跳过违规记录。