Đặt tên ứng dụng
Nếu bạn muốn chạy nhiều tiến trình, bạn cần biết chúng đang kết nối từ đâu. PGBouncer sẽ làm cho điều này vô hình pg_stat_activity
. Giải quyết vấn đề này bằng cách cẩn thận thiết lập application_name
thông tin bạn cần:
# Sets the application name for this connection in the form of
# application-name:user@host
prog = os.path.basename(sys.argv[0]) or 'desjob'
username = pwd.getpwuid (os.getuid ()).pw_name
hostname = socket.gethostname().split(".")[0]·
args.setdefault('connect_args', {'application_name': "%s:%s@%s" %
(prog, username, hostname)})
args.setdefault('isolation_level', "AUTOCOMMIT")
engine = create_engine(url, **args)
Phiên thích
Sử dụng Phiên vì các yêu cầu từ một đối tượng Động cơ có thể sinh ra và giữ nhiều kết nối. Kết nối với Postgres không tốn kém lắm, với PGBouncer, nó thậm chí còn ít hơn thế. Tôi sẽ luôn luôn sử dụngNullPool
để các kết nối duy nhất bạn sẽ thấy trong Postgres là các kết nối đang thực sự được sử dụng.
from sqlalchemy.pool import Pool, NullPool
engine = create_engine(uri, poolclass=NullPool)
Loại bỏ các giao dịch nhàn rỗi
Nếu mục đích của bạn là sử dụng PGBouncer để mở rộng quy mô thì bắt buộc bạn phải tránh để các giao dịch bị kẹt mở. Để làm điều này bạn cần phải biếnautocommit
về . Điều này không đơn giản với SQLAlchemy ... có ba nơi có thể đặt một cái gì đó gọi là "autocommit":
tự động psycopg2
conn = psycopg2.connect(uri)
conn.autocommit = True
Được coi là không an toàn không an toàn vì SQLAlchemy cần biết những gì đang xảy ra bên dưới.
Phiên tự động
Session = sessionmaker(bind=engine, autocommit=True)
session = Session()
Điều này đòi hỏi phải cẩn thận, bàn giao rõ ràng:
session.begin()
session.execute(...)
session.rollback()
Chức năng gọi và xử lý ngoại lệ là cực kỳ khó khăn vì
begin()
và commit()
không thể lồng nhau:
def A():
session.begin()
...
session.rollback()
def B():
session.begin()
try:
A() # error, already open
Trong chế độ này, psycopg2 autocommit
dường nhưFalse
(mặc định)
Động cơ tự động
Đặt chế độ cách ly Động cơ thành "AUTOCOMMIT"
khi tạo động cơ sẽ thiết lập hành vi mặc định mới có thể không yêu cầu thay đổi mã hiện có.
engine = create_engine(uri, isolation_level="AUTOCOMMIT")
Trong chế độ này psycopg2 autocommit
dường nhưTrue
Vấn đề chính ở đây là cách duy nhất để đảm bảo rằng một khối mã được gói trong một giao dịch là phát ra các câu lệnh theo cách thủ công:
session.execute("BEGIN")
#...
session.execute("COMMIT")