2016-04-26 2 views
1

Вкратце: У меня есть база данных Postgresql, и я подключаюсь к этой базе данных через модуль PPython. Такой сценарий может выглядеть следующим образом:Команда SQL SELECT извлекает незафиксированные данные из базы данных Postgresql

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 выбирать и получать только Paul данные. Затем я вставляю SQL, но без какой-либо фиксации, но второй выбор SQL по-прежнему извлекает как Paul, так и George - и я не хочу этого. Я посмотрел оба на psycopg и Postgresql docs и узнал о ISOLATION LEVEL (see Postgresql и see psycopg2). В PostGreSQL документации это явно говорит (под 13.2.1 Read Committed уровень изоляции.):

Однако, SELECT делает видеть эффекты предыдущих обновлений, выполненных в рамках своей собственной транзакции, даже если они еще не совершили.

Я пробовал различные уровни изоляции, я понимаю, что Read Committed и Repeatable Read не wokr, я подумал, что Serializable может работать, но это не - это означает, что я все еще могу принести неподтвержденные данные с select ,

я мог сделать conn.set_isolation_level(0), где 0 представляет psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT, или я мог бы обернуть execute команды внутри with заявлений (see).

В конце концов, я немного смущен, понимаю ли я транзакции и изоляцию (и поведение select без commit полностью нормальное) или нет. Может кто-нибудь просветить эту тему для меня?

ответ

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

Использование autocommit не решит вашу проблему. Когда autocommit является одним, каждый вставка и обновление автоматически привязаны к базе данных, и все последующие чтения будут видеть эти данные.

Самое необычное, что вы не хотите видеть данные, которые были записаны в базу данных вами. Но если это то, что вы хотите, вам нужно два отдельных соединения, и вы должны убедиться, что ваш выбор выполнен до фиксации.

Смежные вопросы