Skip to main content

postgresql-lock

Lock mechanism implemented with PostgreSQL advisory locks.

Easily implement distributed database locking.

Install

pip install postgresql-lock

Supported database interfaces

  • asyncpg
    • asynchronous
  • psycopg2
    • synchronous
  • psycopg3
    • asynchronous
    • synchronous
  • sqlalchemy (supports version 1 & 2; can use any underlying database interface)
    • asynchronous
    • synchronous

Why would I use this?

  • PostgreSQL table locks aren't sufficient for your use-case
  • PostgreSQL row locks don't work on INSERT
  • You want to prevent race conditions between INSERT and UPDATE on the same primary key
  • None of the aforementioned details fit your use-case, but you have PostgreSQL installed and need to prevent race conditions in a distributed system

Default operation

By default postgresql-lock will use session lock scope in blocking mode with rollback_on_error enabled. The session lock scope means only a single database connection can acquire the lock at a time.

Usage

All work revolves around the Lock class.

The easiest way to use Lock is with with or async with statements. The lock will be released automatically. If rollback_on_error is enabled (default), rollbacks are automatically handled prior to release.

Using with and async with implies blocking mode.

from postgresql_lock import Lock

# setup connection
conn = ...

# create and use lock
with Lock(conn, "shared-identifier"):
    print("Acquired lock!")

    # do something here

Now compare the above example to the equivalent try/finally example below:

from postgresql_lock import Lock

# setup connection
conn = ...

# create lock
lock = Lock(conn, "shared-identifier")

try:
    # acquire lock
    lock.acquire()

    print("Acquired lock!")

    try:
        # do something here
        pass

    except Exception as exc:
        # handle_error() will rollback the transaction by default
        lock.handle_error(exc)

        raise exc
finally:
    # release lock (this is safe to run even if the lock has not been acquired)
    lock.release()

Asynchronous usage (without async with)

from postgresql_lock import Lock

# setup connection
conn = ...

# create lock
lock = Lock(conn, "shared-identifier")

try:
    # acquire lock
    await lock.acquire_async()

    print("Acquired lock!")

    try:
        # do something here
        pass

    except Exception as exc:
        # handle_error_async() will rollback the transaction by default
        await lock.handle_error_async(exc)

        raise exc
finally:
    # release lock (this is safe to run even if the lock has not been acquired)
    await lock.release_async()

Non-blocking mode (supports async as well)

from postgresql_lock import Lock

# setup connection
conn = ...

# create lock
lock = Lock(conn, "shared-identifier")

# acquire lock
if lock.acquire(block=False):
    # do something here
    pass

else:
    # could not acquire lock
    pass

# release lock (this is safe to run even if the lock has not been acquired)
lock.release()

Specify the database interface manually

from postgresql_lock import Lock

# setup connection
conn = ...

# create and use lock
lock = Lock(conn, "shared-identifier", interface="asyncpg")

# do things with the lock

Handle rollbacks manually

from postgresql_lock import Lock

# setup connection
conn = ...

# create and use lock
lock = Lock(conn, "shared-identifier", rollback_on_error=False)

# do things with the lock

Changelog

  • 0.2.2
    • Fix: error raised when releasing transaction level locks
  • 0.2.1
    • Moved public Lock fields to properties
  • 0.1.9
    • Fix: release_async() bug for sqlalchemy connections
  • 0.1.8
    • Add logger() function
    • Use "postgresql_lock" logger name
  • 0.1.7
    • Add logging statements
  • 0.1.6
    • Use int.from_bytes() to convert lock key into integer
    • Fix: psycopg3 close() not being awaited bug
  • 0.1.5
    • Rename package from postgres-lock to postgresql-lock
  • 0.1.4
    • Add py.typed for mypy
  • 0.1.3
    • Key can be any object
  • 0.1.2
    • Add Lock.rollback_on_error (default true)
    • Add Lock.handle_error() & Lock.handle_error_async()
  • 0.1.1
    • Key can be str or int

Release files for postgresql-lock 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for postgresql-lock 0.2.2
File Size Uploaded
postgresql_lock-0.2.2.tar.gz 7.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for postgresql-lock 0.2.2
File Interpreter ABI Platform
postgresql_lock-0.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 18.0 kB

Release files / postgresql_lock-0.2.2.tar.gz

Download URL postgresql_lock-0.2.2.tar.gz
Size 7.6 kB
Tags Source
SHA-256 checksum
How to use checksums
48135101d3daafbc4b81c6adb8f8e448ae30d84535e0f2cfa9beb0f6f4cf911f
BLAKE2b-256 checksum
How to use checksums
b7637e05c9c85933b2a390bbb3e00b74a6fa9968f28fee8d67796d7f348d714e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.1.3 CPython/3.12.3 Linux/6.11.0-29-generic

Release files / postgresql_lock-0.2.2-py3-none-any.whl

Download URL postgresql_lock-0.2.2-py3-none-any.whl
Size 10.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
12b3850ac76b7891d27fc5fce26cab33294b25c198a46f09cfd2588941ea433d
BLAKE2b-256 checksum
How to use checksums
69f88a8a389b328d540f06a6990c4b30fef1009337661f73aecd8e4d7d333c01
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.1.3 CPython/3.12.3 Linux/6.11.0-29-generic

Release history Release notifications | RSS feed

This release

0.2.2 This release

2 release files

0.2.1

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page