Skip to content

Instantly share code, notes, and snippets.

@chrisplim
Last active May 13, 2025 07:06
Show Gist options
  • Select an option

  • Save chrisplim/3e69275c6ff2b8b455a9dbf618333900 to your computer and use it in GitHub Desktop.

Select an option

Save chrisplim/3e69275c6ff2b8b455a9dbf618333900 to your computer and use it in GitHub Desktop.
sqlalchemy autocommit
from contextlib import contextmanager
from typing import Iterator
from sqlalchemy import BigInteger, Engine, create_engine
from sqlalchemy.engine.url import URL
from sqlalchemy.orm import DeclarativeBase, Mapped, Session, mapped_column
Column = mapped_column
def create_autocommit_engine() -> Engine:
url = URL.create(
drivername="mysql+pymysql",
username="root",
password="strong_password",
host="127.0.0.1",
port=3306,
database="mydb",
)
options = {
"pool_size": 1,
"max_overflow": 0,
"pool_pre_ping": True,
"pool_use_lifo": True,
"connect_args": {"connect_timeout": 1},
}
return create_engine(
url,
**options,
pool_reset_on_return=None,
isolation_level="AUTOCOMMIT",
future=True,
execution_options={
"autocommit": True,
"isolation_level": "AUTOCOMMIT",
},
)
@contextmanager
def with_readonly_session(engine: Engine) -> Iterator[Session]:
connection = engine.connect()
connection.execution_options(isolation_level="AUTOCOMMIT", reset_on_return=False, expire_on_commit=False)
session = Session(connection)
try:
yield session
finally:
session.close()
class Base(DeclarativeBase):
pass
class TestTable(Base):
__tablename__ = "test_table"
id: Mapped[int] = Column(BigInteger(), primary_key=True, autoincrement=True)
def __init__(self, *, id: int | None = None):
self.id = id
def main() -> None:
engine = create_autocommit_engine()
TestTable.metadata.create_all(engine)
with with_readonly_session(engine) as session:
session.query(TestTable).all()
if __name__ == "__main__":
main()
@chrisplim
Copy link
Author

sqlalchemy version: 2.0.25

uv add sqlalchemy==2.0.25

using docker mysql version 8.4.5

docker run --name isolation-test -e MYSQL_ROOT_PASSWORD=strong_password -p 3306:3306 -d mysql:8.4.5

create the mydb database and configure

mysql -A -h 127.0.0.1 -P 3306 -uroot -pstrong_password

mysql> create database mydb;
Query OK, 1 row affected (0.02 sec)

mysql> SET GLOBAL general_log = 'ON';
Query OK, 0 rows affected (0.01 sec)

mysql> SHOW VARIABLES LIKE 'general_log_file';
+------------------+---------------------------------+
| Variable_name    | Value                           |
+------------------+---------------------------------+
| general_log_file | /var/lib/mysql/8d6575ec6553.log |
+------------------+---------------------------------+
1 row in set (0.05 sec)

Run the test script:

PYTHONPATH=. uv run test_autocommit_behavior.py

Get the docker container and exec

docker ps | grep mysql
8d6575ec6553   mysql:8.4.5                     "docker-entrypoint.s…"   4 days ago     Up 4 days   33060/tcp, 0.0.0.0:3306->3306/tcp   isolation-test

docker exec -it 8d6575ec6553 /bin/bash

in the docker container, tail the logs

tail -f /var/lib/mysql/8d6575ec6553.log
2025-05-13T06:28:06.889193Z	  956 Connect	[email protected] on mydb using TCP/IP
2025-05-13T06:28:06.899971Z	  956 Query	SET NAMES utf8mb4
2025-05-13T06:28:06.901515Z	  956 Query	SET AUTOCOMMIT = 0
2025-05-13T06:28:06.902613Z	  956 Query	SET NAMES utf8mb4
2025-05-13T06:28:06.903381Z	  956 Query	SET AUTOCOMMIT = 1
2025-05-13T06:28:06.908709Z	  956 Query	SELECT VERSION()
2025-05-13T06:28:06.915673Z	  956 Query	SELECT DATABASE()
2025-05-13T06:28:06.917311Z	  956 Query	SELECT @@transaction_isolation
2025-05-13T06:28:06.919415Z	  956 Query	SELECT @@sql_mode
2025-05-13T06:28:06.922564Z	  956 Query	SELECT @@lower_case_table_names
2025-05-13T06:28:06.923313Z	  956 Query	ROLLBACK
2025-05-13T06:28:06.924244Z	  956 Query	DESCRIBE `mydb`.`test_table`
2025-05-13T06:28:06.945557Z	  956 Query	COMMIT
2025-05-13T06:28:06.950147Z	  956 Query	SELECT test_table.id AS test_table_id
FROM test_table
2025-05-13T06:28:06.954183Z	  956 Query	ROLLBACK

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment