SQLAlchemy - Соединения и транзакции с базой
Применение SQLAlchemy Core с точки зрения образования соединений и транзакций с базой.
Как сказано в документации, есть Engine, который скрывает за собой пул и диалект.
подход такой: нужно брать соединения, делать некий логически связанный блок действий, и вызывать conn.close(), которое возвращает соединение в пул.
соединение находится всегда в транзакции.
В процессе работы имеете действие с
если использовать соединения для выборки данных и оставить его у себя
Для долго работающих скриптов очень важно правильно закрывать ресурсы.
Engine - самая важная штука, создавать его рекомендуется по одному на пару "поток программы-база", engine скрывает за собой диалект и пул. Создается функцией create_engine.
Пример 1 - прочитать из базы значение подробнее
engine = create_engine(f'postgresql://user:password@localhost:5432/db')
conn = engine.connect()
result = conn.execute("select name from host LIMIT 1")
for row in result:
print("name:", row['name'])
# idle in transaction
result.close() # ничего не меняется
conn.close() # ROLLBACK, соединение не закрывается, возвращается в пул
первая особенность: соединение не закрывается. Иногда его таки нужно закрыть. Есть два способа:
- вызвать engine.dispose()
- использовать другой pool
вторая особенность: после показа всех значений состояние остается idle in transaction. Решения 2:
- conn.execute("COMMIT")
- совет из док.: conn.execute(text("select name from host LIMIT 1").execution_options(autocommit=True))
- вернуть соединение в пул - conn.close() - как в данном примере
третья особенность: все данные сразу попадают из execute в result. Решение для больших данных: использовать серверный курсор.
Пример 2 - прочитать из базы значение подробнее
engine = create_engine(f'postgresql://user:password@localhost:5432/db')
result = engine.execute("select name from host LIMIT 1")
for row in result:
print("name:", row['name'])
с этим примеров все в порядке, однако сложности возникают если не прочитать result до конца или вообще не читать, для надежности лучше всегда вызывать result.close()
Пример 3 - Обновить значение
engine = create_engine(f'postgresql://user:password@localhost:5432/db')
conn = engine.connect()
conn.execute("UPDATE host SET name = 'test1' WHERE host_id = 713")
# idle, COMMIT
conn.close() # COMMIT, соединение не закрывается, возвращается в пул
тут все нормально