aio-libs / aio-libs/aiomysql

Default autocommit should be None to avoid unintended transactions

Aperta
#999 2 commenti 0 reazioni 0 assegnatari Vedi su GitHub
bug
Lingua principale
Python
Stelle
1.9k
Fork
272
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Descrizione

### Describe the bug

**Issue Description:**

When initializing a connection in `aiomysql`, the default value of `autocommit` is explicitly set to `False`, which overrides the server's default configuration (typically `True`). This leads to unexpected behavior where transactions are implicitly started but never committed, causing long-running transactions and potential table-locking issues.

### Problem Details:

1. **Autocommit Mismatch**:

* If the MySQL server has `autocommit=True` (default), but `aiomysql` forces `autocommit=False` during connection initialization, the session enters a state where every `SELECT` query starts an implicit transaction.
* Example:


```python
# aiomysql connection setup with autocommit=False (default)
conn = await aiomysql.connect(..., autocommit=False)
```

This executes `SET autocommit=0` on the server, overriding its default configuration.

1. **Transaction Leak**:

* After executing a query (e.g., `SELECT`), the transaction remains open because `autocommit=False`.
* When releasing the connection back to the pool, `aiomysql` checks `conn.server_status` to determine if a transaction is active. However, due to a bug in status tracking, it incorrectly assumes no transaction is active and returns the connection to the pool *without committing or rolling back*.
* The open transaction persists in the connection pool, leading to table locks (e.g., schema changes blocked by `METADATA LOCK`).
2. **Root Cause**:

* The `autocommit` parameter in `aiomysql.connect()` defaults to `False`, conflicting with the server's actual configuration.
* The library does not respect the server's `autocommit` value by default, forcing unnecessary transactions.

### Proposed Fix:

Set the default value of `autocommit` to `None` in `aiomysql.Connection`, which would:

1. **Respect Server Configuration**: Do not send `SET autocommit=...` unless explicitly specified by the user.
2. **Avoid Implicit Transactions**: If the server defaults to `autocommit=True`, no transaction is started for read-only queries.

### References:

* MySQL Behavior: [[autocommit Documentation](https://dev.mysql.com/doc/refman/8.0/en/innodb-autocommit-commit-rollback.html)](https://dev.mysql.com/doc/refman/8.0/en/innodb-autocommit-commit-rollback.html)
* Related Code: `aiomysql` forcibly sets `autocommit` during initialization

![Image](https://github.com/user-attachments/assets/c6877c2a-7d85-438a-91a3-0b7b8d3efd4e)

![Image](https://github.com/user-attachments/assets/c5bd1edb-7a83-4256-8507-d5cf9427b110)

---

**Suggested Code Change:**
Modify the `autocommit` default in `aiomysql.Connection.__init__` from `False` to `None`:

```python
def __init__(..., autocommit=None, ...):
...
```

This ensures the server's `autocommit` configuration is respected unless explicitly overridden by the user.

---

Let me know if you need further details or testing assistance! 🙌

### To Reproduce

1. mysql server default autocommit=True.
2. Initialize a connection pool without parameter `autocommit`.
3. Execute a `SELECT` query and release the connection back to the pool.
4. Observe the transaction status in MySQL (`SHOW PROCESSLIST` or `INFORMATION_SCHEMA.INNODB_TRX`), which shows an open transaction even after the connection is "closed".

### Expected behavior

**Respect Server Configuration**: Do not send `SET autocommit=...` unless explicitly specified by the user.

or commit transaction when release conn to pool

### Logs/tracebacks

```python-traceback
MySQL mydb@127.0.0.1:mydb> SELECT * FROM `performance_schema`.`metadata_locks` LIMIT 0,100 \G;
***************************[ 1. row ]***************************
OBJECT_TYPE | TABLE
OBJECT_SCHEMA | mydb
OBJECT_NAME | table_name
COLUMN_NAME |
OBJECT_INSTANCE_BEGIN | 140514755781136
LOCK_TYPE | SHARED_READ
LOCK_DURATION | TRANSACTION
LOCK_STATUS | GRANTED
SOURCE | sql_parse.cc:6142
OWNER_THREAD_ID | 902740
OWNER_EVENT_ID | 3

auto start transaction for select.
```

### Python Version

```console
$ python --version
Python 3.10.14
```

### aiomysql Version

```console
$ python -m pip show aiomysql
Name: aiomysql
Version: 0.2.0
Summary: MySQL driver for asyncio.
Home-page: https://github.com/aio-libs/aiomysql
Author: Nikolay Novik
Author-email: nickolainovik@gmail.com
License: MIT
```

### PyMySQL Version

```console
$ python -m pip show PyMySQL
Name: PyMySQL
Version: 1.1.1
Summary: Pure Python MySQL Driver
Home-page:
Author:
Author-email: Inada Naoki , Yutaka Matsubara
License: MIT License
```

### SQLAlchemy Version

```console
$ python -m pip show sqlalchemy
Name: SQLAlchemy
Version: 1.4.54
Summary: Database Abstraction Library
Home-page: https://www.sqlalchemy.org
Author: Mike Bayer
Author-email: mike_mp@zzzcomputing.com
License: MIT
```

### OS

Linux diaochan.huoban.ai 5.15.0-125-generic #135-Ubuntu SMP Fri Sep 27 13:53:58 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
or
Darwin Mac.local 24.4.0 Darwin Kernel Version 24.4.0: Wed Mar 19 21:16:34 PDT 2025; root:xnu-11417.101.15~1/RELEASE_ARM64_T6000 arm64

### Database type and version

```console
SELECT VERSION();
8.0.40-0ubuntu0.22.04.1
```

### Additional context

_No response_

### Code of Conduct

- [x] I agree to follow the aio-libs Code of Conduct

Guida per i contributori

Apri la guida per i contributori

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.