SQL命令SELECT从Postgresql数据库中提取未提交的数据

时间:2016-04-26 13:27:30

标签: python postgresql transactions psycopg2

简而言之: 我有Postgresql数据库,我通过Python的psycopg2模块连接到该数据库。这样的脚本可能如下所示:

import psycopg2

# connect to my database
conn = psycopg2.connect(dbname="<my-dbname>",
                        user="postgres",
                        password="<password>",
                        host="localhost",
                        port="5432")

cur = conn.cursor()

ins  = "insert into testtable (age, name) values (%s,%s);"
data = ("90", "George")

sel = "select * from testtable;"

cur.execute(sel)
print(cur.fetchall())
# prints out
# [(100, 'Paul')]
# 
# db looks like this
# age | name
# ----+-----
# 100 | Paul

# insert new data - no commit!
cur.execute(ins, data)
# perform the same select again
cur.execute(sel)
print(cur.fetchall())
# prints out
# [(100, 'Paul'),(90, 'George')]
#
#  db still looks the same
# age | name
# ----+-----
# 100 | Paul
cur.close()
conn.close()

也就是说,我连接到脚本开头的那个数据库:

age | name
----+-----
100 | Paul

我执行SQL select并仅检索Paul数据。然后我做SQL插入,但没有任何提交,但第二个SQL选择仍然提取PaulGeorge - 我不想要这样。我已查看了psycopg和Postgresql文档,并了解了ISOLATION LEVELsee Postgresqlsee psycopg2)。在Postgresql文档(13.2.1。读提交的隔离级别)中,它明确地说:

  

但是,SELECT确实看到了在自己的事务中执行的先前更新的效果,即使它们尚未提交。

我已经尝试过不同的隔离级别,我明白,我认为Read CommittedRepeatable Read并不是Serializable可能会有效,但确实如此不 - 意味着我仍然可以使用select获取未提交的数据。

我可以conn.set_isolation_level(0),其中0代表psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT,或者我可以将execute命令包含在with语句中see )。

毕竟,我有点困惑,我是否理解交易和隔离(以及select没有commit的行为是完全正常的)或不是。有人可以启发这个话题吗?

2 个答案:

答案 0 :(得分:2)

您的两个SELECT语句使用相同的连接,因此使用相同的事务。来自the psycopg manual you linked

  

默认情况下,第一次将命令发送到数据库时......会创建一个新事务。以下数据库命令将在同一事务的上下文中执行。

因此,您的代码等同于以下内容:

BEGIN TRANSACTION;
select * from testtable;
insert into testtable (age, name) values (90, 'George');
select * from testtable;
ROLLBACK TRANSACTION;

隔离级别控制事务与其他事务交互的方式。在事务中,您始终可以看到该事务中命令的效果。

如果要隔离代码的两个不同部分,则需要打开两个与数据库的连接,每个连接(除非您启用自动提交)创建一个单独的事务。

请注意,根据已链接的文档,创建新光标是不够的:

  

...不仅是第一个游标发出的命令,而是由同一个连接创建的所有游标发出的命令

答案 1 :(得分:1)

使用自动提交无法解决您的问题。当autocommit为1时,每次插入和更新都会自动提交到数据库,所有后续读取都会看到该数据。

不希望看到您已经写入数据库的数据,这是最不寻常的。但如果这是你想要的,你需要两个独立的连接,你必须确保在提交之前执行你的选择。