The pgdbpool Python module is a tiny PostgreSQL Database Connection De-Multiplexer, primarily designed for Web- / Application Servers.
Key Features:
- Multi-endpoint support: Load balance across multiple PostgreSQL servers
- Flexible threading models: Choose between threaded and non-threaded modes
- Transaction control: Manual commit support for complex transactions
- High availability: Built-in failover and connection management
+----------------------+ +---------------------
| WebServer Service.py | -- Handler Con #1 ----> | PostgreSQL
| Request / Thread #1 | | Backend #1
+----------------------+ |
|
+----------------------+ |
| WebServer Service.py | -- Handler Con #2 ----> | PostgreSQL
| Request / Thread #2 | | Backend #2
+----------------------+ +---------------------
The connection pool now supports multiple PostgreSQL database endpoints for load balancing and high availability:
- β Configure multiple database hosts in the configuration
- β Connections are automatically distributed across available endpoints
- β Provides built-in load balancing for read operations
- β Enhances fault tolerance and scalability
If configured in a Web Server's WSGI Python script, the pooling logic is straightforward:
- Check if a free connection in the pool exists.
- Verify if the connection is usable (SQL ping).
- Use the connection and protect it from being accessed until the query/queries are completed.
- Release the connection for reuse.
- Reconnect to the endpoint if the connection is lost.
The pool now supports two threading models that can be configured based on your application's architecture:
threaded
(default): Usesthreading.Lock()
for thread safety, suitable for traditional multi-threaded web serversnon-threaded
: Disables locking for single-threaded applications, eliminating GIL overhead
Thread safety is ensured via lock = threading.Lock()
, which relies on a kernel mutex syscall()
.
While this concept works, the GIL (Global Interpreter Lock) in Python thwarts scalability under heavy loads in a threaded Web Server setup.
For applications using a single-threaded, process-per-request model (like the FalconAS Python Application Server), the non-threaded mode provides:
- No locking overhead - eliminates mutex syscalls
- Better performance - avoids GIL contention
- Simpler architecture - designed for 1 Process == 1 Python Interpreter
Important
Refer to Section 6: Future for more details on threading-less architectures.
Python 3 and the psycopg2 module are required.
# install (debian)
apt-get install python3-psycopg2
pip install pgdbpool
See documentation either at ./doc
or https://pythondocs.webcodex.de/pgdbpool/v1.0
for detailed explanation / illustrative examples.
config = {
'db': [
{
'host': 'postgres-server-1.example.com',
'name': 'mydb',
'user': 'dbuser',
'pass': 'dbpass'
},
{
'host': 'postgres-server-2.example.com',
'name': 'mydb',
'user': 'dbuser',
'pass': 'dbpass'
}
],
'groups': {
'default': {
'connection_count': 20,
'autocommit': True
}
}
}
# for non-threaded applications (e.g., FalconAS)
config = {
'type': 'non-threaded',
'db': { ... },
'groups': { ... }
}
# for traditional threaded applications (default)
config = {
'type': 'threaded', # or omit for default
'db': { ... },
'groups': { ... }
}
import pgdbpool as dbpool
dbpool.Connection.init(config)
# for autocommit=False connections
with dbpool.Handler('group1') as db:
db.query('INSERT INTO table1 VALUES (%s)', ('value1',))
db.query('INSERT INTO table2 VALUES (%s)', ('value2',))
db.commit() # Manual commit
The DB-pooling functionality is now compatible with the FalconAS Python Application Server (https://github.com/WEBcodeX1/http-1.2).
The implemented model: 1 Process == 1 Python Interpreter (threading-less),
effectively solving the GIL issue through the non-threaded
configuration mode.
The pool now supports multiple (read-load-balanced) PostgreSQL endpoints:
- β Implemented: Multiple database endpoint configuration
- β Implemented: Automatic connection distribution across endpoints
- β Implemented: Built-in load balancing for database connections
- β Implemented: Read / write / endpoint group separation