Giter Site home page Giter Site logo

jkklee / pymysql-pool Goto Github PK

View Code? Open in Web Editor NEW
172.0 172.0 50.0 95 KB

A simple but robust connection pool (with multiplexing) base on PyMySQL, mainly used for multi threads mode, which also compatible with single thread mode.

License: GNU General Public License v3.0

Python 100.00%
connection-pool mysql pymysql-connection-pool pymysql-multi-thread pymysql-pool python python-mysql-multithread python-mysql-pool

pymysql-pool's Issues

hanging after the sql update command done

The script is hanging after done sql update command:
when I used Ctrl-Z to kill the process, I got the following message.
How can I solve the issue?
Exception ignored in: <module 'threading' from '/mnt/users/resops_user/services/py3.8/lib/python3.8/threading.py'>
Traceback (most recent call last):
File "/mnt/users/resops_user/services/py3.8/lib/python3.8/threading.py", line 1388, in _shutdown
lock.acquire()
KeyboardInterrupt:

AttributeError: module 'pymysqlpool' has no attribute 'ConnectionPool'

I got this error:

Traceback (most recent call last):
File "/usr/src/app/./main.py", line 42, in
db_manager = DatabaseService(app.config)
File "/usr/src/app/./services/database_service.py", line 19, in init
self.pool = pymysqlpool.ConnectionPool(

on docker debian dist:

No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 12 (bookworm)
Release: 12
Codename: bookworm

But in Windows 10 it works. There are the same version of python and same version of the packages.

import pymysql.cursors
import pymysqlpool
import time
from log.log import Log

Inicializando el logger

logger = Log.get_logger()

class DatabaseService:
def init(self, config):
"""
Constructor de la clase DatabaseManager. Inicializa la conexión
al pool de conexiones con la configuración proporcionada.

    :param config: Diccionario con la configuración de la base de datos.
    """
    self.pool = pymysqlpool.ConnectionPool(
        host=config['MYSQL_HOST'],
        user=config['MYSQL_USER'],
        password=config['MYSQL_PASSWORD'],
        db=config['MYSQL_DB'],
        cursorclass=pymysql.cursors.DictCursor,
        autocommit=True,
        size=5,
        maxsize=7,
        pre_create_num=2,
        name='pool1'
    )
    self.connection = None

def __enter__(self):
    """
    Método especial para permitir el uso de DatabaseManager
    dentro de un bloque with.

    :return: Una conexión a la base de datos.
    """
    self.connection = self.get_connection_with_retry()
    return self.connection

def __exit__(self, exc_type, exc_val, exc_tb):
    """
    Método especial que se llama cuando se sale del bloque with,
    asegurando que la conexión se cierre.

    :param exc_type: Tipo de excepción.
    :param exc_val: Valor de la excepción.
    :param exc_tb: Traceback de la excepción.
    """
    self.close()

def get_connection_with_retry(self, max_retries=5, delay=1):
    """
    Intenta obtener una conexión del pool, reintentando hasta
    max_retries veces con un retraso de delay segundos entre intentos.

    :param max_retries: Número máximo de reintentos.
    :param delay: Retraso entre reintentos en segundos.
    :return: Una conexión a la base de datos.
    """
    retry_count = 0
    while retry_count < max_retries:
        try:
            return self.pool.get_connection()
        except pymysqlpool.GetConnectionFromPoolError:
            retry_count += 1
            time.sleep(delay)
    logger.error(f"Can't get connection after {max_retries} retries")
    raise pymysqlpool.GetConnectionFromPoolError(f"Can't get connection after {max_retries} retries")

def close(self):
    """
    Cierra la conexión actual a la base de datos si existe.

    """
    if self.connection is None:
        logger.warning("No connection to close.")
    else:
        try:
            self.connection.close()
            self.connection = None
            logger.info("Connection closed successfully.")
        except Exception as e:
            logger.error(f"Error closing connection: {e}")

多线程情况下问题

我实现了连接池单例类,在多线程的情况下,会出现retry_counter没有定义的情况。

stubfile

Hi

Any plan to add stub file? Type checkers are complaining.
Thank you

How do i connect to my Mysql server using SSHClient.

This is my code for the same.

Code:
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(**gb.ssh_config, look_for_keys=False)
ssh_channel = ssh_client.get_transport().open_channel(
'direct-tcpip',
('127.0.0.1', gb.dev_db_config["port"]),
(gb.dev_db_config["host"], gb.dev_db_config["port"]),
)
mysql_connection = pymysqlpool.ConnectionPool(
host='x.x.x.x',
port=3306,
user="admin",
password="Admin@123",
database='ai_netra'
)

Help me with this.

a little problem with pool size but it doesn't matter

  • NEW
class ConnectionPool:
    _HARD_LIMIT = 100
    _THREAD_LOCAL = threading.local()
    _THREAD_LOCAL.retry_counter = 0  # a counter used for debug get_connection() method

    def __init__(self, size=5, name=None, *args, **kwargs):
    *   self.size =  size < self._HARD_LIMIT and size or self._HARD_LIMIT
    *   self._pool = queue.Queue(self.size)
        self.name = name if name else '-'.join(
            [kwargs.get('host', 'localhost'), str(kwargs.get('port', 3306)),
             kwargs.get('user', ''), kwargs.get('database', '')])
    *   for _ in range(self.size):
            conn = Connection(*args, **kwargs)
            conn._pool = self
            self._pool.put(conn)

    def put_connection(self, conn):
        if not conn._pool:
            conn._pool = self
        conn.cursor().close()
        try:
            self._pool.put_nowait(conn)
            logger.debug("Put connection back to pool(%s)", self.name)
        except queue.Full:
    *       logger.warning("Put connection to pool(%s) error, pool is full, size:%d", self.name, self.size))

    # def size(self):
    #    return self._pool.qsize()

Inconsistent results

When a record is inserted using one connection from the pool and then selected using a different connection from the pool. The second connection does not find the record.

Not release connection from connection pool

Hi,

After get connection from connection pool, application run below code to make two database insert in a transaction.
The problem is when sql_2 execute fails, the database connection is released.
Would you please help suggest where is wrong.

with conn:
with conn.cursor() as cur:
sql_1= "INSERT INTO T1 (V1, V2) values(%s, %s)"
cur.execute(sql_1, ('Value1', 'Value2'))
sql_2= "INSERT INTO T2 (V3, V4) values(%s, %s)"
cur.execute(sql_2, ('Value3', 'Value4'))
conn.commit()

Lost connection to MySQL server during query

Hello, I have bug in my app. I use this library with threading, so I have pool of 50 connections and 1-3 threading running at the same time. After a while my app was running, my threading can't pass data to DB. I decided to look at logs and I founded this error
[Thread-21][2020-07-29 07:10:10] (2013, 'Lost connection to MySQL server during query')

I think this is happened because I didn't use connection in some long time.
How I can fix it?

problems using the Context Manager Protocol

Hi,
I am experiencing problems using the Context Manager Protocol. it seems doesn't release the connections, while manually it works fine.
Env:

pymysql-pool-0.3.5
Python 3.9.5
OS: "Raspbian GNU/Linux 10 (buster)" 

Using the following code and running 3 queries:


print("pool size before....:", ResourcesPool.size())
conn=ResourcesPool.get_connection()
logger.warning("Using Context_Manager_Protocol")
with conn as cur:
      data=cur.execute_query(query=query_string, args=field_values)
print("pool size after....:", ResourcesPool.size())

I get:

query-01
    pool size before....: 0
    pool size after....: 4
query-02
    pool size before....: 4
    pool size after....: 7
query-03
    pool size before....: 7
    pool size after....: 10

on the next query I get:

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/pi/.local/lib/python3.9/site-packages/pymysqlpool.py", line 184, in put_connection
    self._pool.put_nowait(conn)
  File "/usr/local/lib/python3.9/queue.py", line 191, in put_nowait
    return self.put(item, block=False)
  File "/usr/local/lib/python3.9/queue.py", line 137, in put
    raise Full
queue.Full

.... until stack is full

Instead using the following:

print("pool size before....:", ResourcesPool.size())
conn=ResourcesPool.get_connection()

try:
    cur=conn.cursor()
    cur.execute(query=query_string, args=field_values)
    data=cur.fetchall()
except (Exception) as e:
    logger.error(str(e))
    return None
    # raise
finally:
    conn.close()
print("pool size after....:", ResourcesPool.size())

I get:

query-01
    pool size before....: 0
    pool size after....: 1
query-02
    pool size before....: 1
    pool size after....: 1
query-03
    pool size before....: 1
    pool size after....: 1

Is there a my error?
Pool_jeekie_ISSUE.py.txt
Regards

Avoid Adding Log Handler To The Root Logger

Hi, shall we move the log handler from the root logger to the logger created in this module?

The current implementation calls logging.basicConfig, which will create a handler to root logger. In this approach, other loggers will print to stderr after importing this library because of the handler in the root logger.

We can simply resolve this issue by creating the handler in the logger instead of calling logging.basicConfig which adds to the root logger. How do you feel about this?

def _add_handler(logger: logging.Logger) -> None:
    handler = logging.StreamHandler()
    handler.setFomatter(
        logging.Formatter(
            fmt="%(asctime)s %(levelname)8s: %(message)s",
            datefmt="%m-%d %H:%M:%S",
        )
    )
    logger.addHandler(handler)

_add_handler(logger)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.