PyMySQLLock

0.2.0 · active · verified Thu Apr 16

PyMySQLLock is a Python library that provides a MySQL-backed distributed locking primitive. It enables multiple application instances to coordinate and ensure that only one instance holds a specific lock at a time, performing tasks that require exclusive access. As of version 0.2.0, it aims to be a lightweight solution when MySQL is the primary dependency for application uptime and health, rather than relying on external systems like ZooKeeper or etcd. The project appears stable with a moderate release cadence.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to acquire and release a named MySQL-backed lock. It configures the MySQL connection using environment variables for security, attempts to acquire a lock with a timeout, performs a simulated task if successful, and ensures the lock is released and the connection closed.

import os
from PyMySQLLock import Locker

# --- Configuration (use environment variables for security) ---
MYSQL_HOST = os.environ.get('MYSQL_HOST', 'localhost')
MYSQL_USER = os.environ.get('MYSQL_USER', 'root')
MYSQL_PASSWORD = os.environ.get('MYSQL_PASSWORD', 'password')
MYSQL_DB = os.environ.get('MYSQL_DB', 'test_db')

LOCK_NAME = 'my_critical_task_lock'
ACQUIRE_TIMEOUT = 10 # seconds

def run_task_with_lock():
    locker = None
    try:
        # Locker uses connection parameters compatible with common MySQL drivers (e.g., PyMySQL)
        locker = Locker(
            host=MYSQL_HOST,
            user=MYSQL_USER,
            password=MYSQL_PASSWORD,
            database=MYSQL_DB
        )
        lock = locker.lock(LOCK_NAME)

        print(f"Attempting to acquire lock '{LOCK_NAME}' with a {ACQUIRE_TIMEOUT}s timeout...")
        # Try to acquire the lock. Default timeout is -1 (infinite wait).
        # Setting refresh_interval_secs keeps the connection alive for long-held locks.
        if lock.acquire(timeout=ACQUIRE_TIMEOUT, refresh_interval_secs=5):
            print(f"Successfully acquired lock '{LOCK_NAME}'. Performing critical task...")
            # Simulate work
            import time
            time.sleep(5)
            print("Critical task completed.")
        else:
            print(f"Failed to acquire lock '{LOCK_NAME}' within {ACQUIRE_TIMEOUT} seconds. Another instance might hold it.")
    except Exception as e:
        print(f"An error occurred: {e}")
    finally:
        if 'lock' in locals() and lock.is_acquired():
            print(f"Releasing lock '{LOCK_NAME}'.")
            lock.release()
        if locker:
            locker.close_connection()
            print("MySQL connection closed.")

if __name__ == "__main__":
    print("Ensure MySQL server is running and database exists.")
    print("Set MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DB environment variables if not using defaults.")
    run_task_with_lock()

view raw JSON →