Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to reconnect database backend after nested transaction exception. #538

Open
ODD2 opened this issue Mar 18, 2023 · 1 comment
Open

Comments

@ODD2
Copy link

ODD2 commented Mar 18, 2023

Issue

Dear Community,

The issue occurs within nested transactions as soon as a short period of disconnection from the database, the databases couldn't automatically reconnect the target database but rather repetitively throws the same exception: InterfaceError("(0, 'Not Connected')").

I'm able to constantly reproduce the issue with a short example code.
(Please build a simple MySQL database, configure the example code to connect the database backend on line 8, and fetch arbitrary data from the database on line 27.)

import sys

import asyncio
import databases


api_db = databases.Database(
    "mysql+aiomysql://root:password@mysql-test:3306/testing_db", # the database URL, the selected backend is aiomysql
    min_size=1,
    max_size=1
)


# the nested transaction driver function, the default depth of the nest is 3 layers.
async def driver(layer=2):
    try:
        print(f"{layer}:enter driver")
        async with api_db.transaction(): # start transaction
            print(f"{layer}:start transaciton")
            if (layer > 0):
                print(f"{layer}:enter a transaction nest.")
                await asyncio.sleep(1)
                await driver(layer-1) # enter next depth
            else:
                print(f"{layer}:fetch data from users table.")
                await api_db.fetch_all("SELECT * FROM `users` WHERE 1;") # fetch arbitrary data from databases
                print(f"{layer}:fetch done.")
    except Exception as e:
        raise e
    finally:
        print(f"{layer}:exit driver") 


async def main():
    await api_db.connect() # connect to the database
    while True: 
        try:
            await driver() 
        except Exception as e:
            print(f"exception occured {repr(e)}")
        else:
            print("complete successfully")
        await asyncio.sleep(1)

if __name__ == "__main__":
    asyncio.run(main())

To reproduce the issue, simply disconnect the database backend while the process enters a nested transaction(e.g. when the message "1:enter a transaction nest" prompts in the terminal).

System

OS: 
	- Ubuntu 20.04
PYTHON: 
	- 3.8.16
DATABASES VERSION:
	- 0.7.0
DATABASE BACKEND: 
	- mysql
DATABASE DRIVER: 
	- aiomysql
INSTALLED PACKAGES:
	- aiomysql==0.1.1
	- autopep8 @ file:///opt/conda/conda-bld/autopep8_1650463822033/work
	- certifi @ file:///croot/certifi_1671487769961/work/certifi
	- cffi==1.15.1
	- cryptography==39.0.0
	- databases==0.7.0
	- greenlet==2.0.1
	- pycodestyle @ file:///tmp/build/80754af9/pycodestyle_1636635402688/work
	- pycparser==2.21
	- pydantic==1.10.2
	- PyMySQL==1.0.2
	- SQLAlchemy==1.4.46
	- toml @ file:///tmp/build/80754af9/toml_1616166611790/work
	- typing_extensions==4.4.0
@ODD2
Copy link
Author

ODD2 commented Apr 17, 2023

This issue seems related to the connection leak problem(#498). I've created a pull request #528 similar to #498, which handles the leak problem during the start of a transaction and returns the raised exceptions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant