a3eb4b1b57
- Added Jellyfin.Database.Providers.Postgres project with full EF Core migration support for PostgreSQL. - Implemented automatic database creation and privilege assignment on startup. - Generated initial migration and model snapshot for PostgreSQL schema. - Updated build, test, and dependency files to include PostgreSQL provider and Npgsql packages. - Added PowerShell script for generating and testing PostgreSQL migrations. - No changes to application logic outside database provider/migration infrastructure.
303 lines
7.6 KiB
Markdown
303 lines
7.6 KiB
Markdown
# PostgreSQL Troubleshooting Guide
|
|
|
|
This guide helps resolve common issues when using PostgreSQL with Jellyfin.
|
|
|
|
## SynchronizationLockException Error
|
|
|
|
### Error Message
|
|
```
|
|
System.Threading.SynchronizationLockException: The write lock is being released without being held.
|
|
```
|
|
|
|
### Cause
|
|
This error occurs when using `Pessimistic` locking behavior with PostgreSQL. The issue stems from:
|
|
- EF Core interceptors executing on different threads during async operations
|
|
- `ReaderWriterLockSlim.IsWriteLockHeld` being thread-local, not async-context-aware
|
|
- Transaction and command interceptors both trying to acquire locks
|
|
|
|
### Solution 1: Use NoLock Behavior (Recommended)
|
|
PostgreSQL has built-in MVCC (Multi-Version Concurrency Control) and transaction isolation, making application-level pessimistic locking unnecessary and potentially problematic.
|
|
|
|
**Update your `config/database.xml`:**
|
|
```xml
|
|
<LockingBehavior>NoLock</LockingBehavior>
|
|
```
|
|
|
|
**Complete PostgreSQL Configuration:**
|
|
```xml
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
<DatabaseConfigurationOptions>
|
|
<DatabaseType>Jellyfin-PostgreSQL</DatabaseType>
|
|
<LockingBehavior>NoLock</LockingBehavior>
|
|
<CustomProviderOptions>
|
|
<Options>
|
|
<CustomDatabaseOption>
|
|
<Key>host</Key>
|
|
<Value>localhost</Value>
|
|
</CustomDatabaseOption>
|
|
<CustomDatabaseOption>
|
|
<Key>database</Key>
|
|
<Value>jellyfin</Value>
|
|
</CustomDatabaseOption>
|
|
<CustomDatabaseOption>
|
|
<Key>username</Key>
|
|
<Value>jellyfin</Value>
|
|
</CustomDatabaseOption>
|
|
<CustomDatabaseOption>
|
|
<Key>password</Key>
|
|
<Value>your_password</Value>
|
|
</CustomDatabaseOption>
|
|
</Options>
|
|
</CustomProviderOptions>
|
|
</DatabaseConfigurationOptions>
|
|
```
|
|
|
|
### Solution 2: Fixed Pessimistic Locking (If Needed)
|
|
The pessimistic locking implementation has been updated to use `AsyncLocal<int>` for tracking lock depth across async operations. However, this is **not recommended** for PostgreSQL as it adds unnecessary overhead.
|
|
|
|
If you must use pessimistic locking:
|
|
1. Ensure you have the latest code with the `AsyncLocal` fix
|
|
2. Use with caution as it may impact performance
|
|
3. Monitor for deadlocks in application logs
|
|
|
|
## Connection Issues
|
|
|
|
### Error: "Could not connect to server"
|
|
|
|
**Checks:**
|
|
1. Verify PostgreSQL is running:
|
|
```bash
|
|
# Linux/macOS
|
|
systemctl status postgresql
|
|
|
|
# Windows (PowerShell)
|
|
Get-Service -Name postgresql*
|
|
```
|
|
|
|
2. Test connection manually:
|
|
```bash
|
|
psql -h localhost -U jellyfin -d jellyfin
|
|
```
|
|
|
|
3. Check `pg_hba.conf` authentication settings:
|
|
```
|
|
# Allow local connections
|
|
host jellyfin jellyfin 127.0.0.1/32 md5
|
|
host jellyfin jellyfin ::1/128 md5
|
|
```
|
|
|
|
4. Restart PostgreSQL after changing configuration:
|
|
```bash
|
|
# Linux/macOS
|
|
sudo systemctl restart postgresql
|
|
|
|
# Windows
|
|
Restart-Service postgresql*
|
|
```
|
|
|
|
### Error: "Password authentication failed"
|
|
|
|
1. Reset the password:
|
|
```sql
|
|
ALTER USER jellyfin WITH PASSWORD 'new_secure_password';
|
|
```
|
|
|
|
2. Update `database.xml` with the new password
|
|
|
|
3. Ensure password doesn't contain XML special characters (`<`, `>`, `&`, `'`, `"`). If it does, use XML encoding:
|
|
- `<` → `<`
|
|
- `>` → `>`
|
|
- `&` → `&`
|
|
- `'` → `'`
|
|
- `"` → `"`
|
|
|
|
## Migration Issues
|
|
|
|
### Error: "Database migration failed"
|
|
|
|
1. Check PostgreSQL version:
|
|
```bash
|
|
psql --version
|
|
```
|
|
Minimum required: PostgreSQL 12
|
|
|
|
2. Verify database exists and is accessible:
|
|
```bash
|
|
psql -h localhost -U jellyfin -d jellyfin -c "SELECT version();"
|
|
```
|
|
|
|
3. Check database user permissions:
|
|
```sql
|
|
-- Connect as postgres superuser
|
|
GRANT ALL PRIVILEGES ON DATABASE jellyfin TO jellyfin;
|
|
GRANT ALL PRIVILEGES ON SCHEMA public TO jellyfin;
|
|
```
|
|
|
|
4. Enable detailed logging:
|
|
```xml
|
|
<CustomDatabaseOption>
|
|
<Key>EnableSensitiveDataLogging</Key>
|
|
<Value>True</Value>
|
|
</CustomDatabaseOption>
|
|
```
|
|
|
|
## Performance Issues
|
|
|
|
### Slow Queries
|
|
|
|
1. **Enable Connection Pooling** (should be default):
|
|
```xml
|
|
<CustomDatabaseOption>
|
|
<Key>pooling</Key>
|
|
<Value>True</Value>
|
|
</CustomDatabaseOption>
|
|
```
|
|
|
|
2. **Increase Command Timeout** for large libraries:
|
|
```xml
|
|
<CustomDatabaseOption>
|
|
<Key>command-timeout</Key>
|
|
<Value>60</Value>
|
|
</CustomDatabaseOption>
|
|
```
|
|
|
|
3. **Optimize PostgreSQL** configuration in `postgresql.conf`:
|
|
```
|
|
shared_buffers = 256MB # 25% of RAM for dedicated server
|
|
effective_cache_size = 1GB # 50-75% of RAM
|
|
maintenance_work_mem = 64MB
|
|
checkpoint_completion_target = 0.9
|
|
wal_buffers = 16MB
|
|
default_statistics_target = 100
|
|
random_page_cost = 1.1 # For SSD storage
|
|
effective_io_concurrency = 200 # For SSD storage
|
|
work_mem = 4MB
|
|
```
|
|
|
|
4. **Create Indexes** for common queries (EF Core migrations should handle this, but verify):
|
|
```sql
|
|
-- Check existing indexes
|
|
SELECT * FROM pg_indexes WHERE schemaname = 'public';
|
|
```
|
|
|
|
### High Memory Usage
|
|
|
|
PostgreSQL connection pooling maintains connections. To reduce:
|
|
```xml
|
|
<CustomDatabaseOption>
|
|
<Key>pooling</Key>
|
|
<Value>False</Value>
|
|
</CustomDatabaseOption>
|
|
```
|
|
|
|
⚠️ **Warning**: Disabling pooling will impact performance.
|
|
|
|
## Debugging
|
|
|
|
### Enable Detailed SQL Logging
|
|
|
|
Add to `config/database.xml`:
|
|
```xml
|
|
<CustomDatabaseOption>
|
|
<Key>EnableSensitiveDataLogging</Key>
|
|
<Value>True</Value>
|
|
</CustomDatabaseOption>
|
|
```
|
|
|
|
⚠️ **Security Warning**: This logs SQL queries including parameter values. Only use for debugging and disable in production.
|
|
|
|
### Check Jellyfin Logs
|
|
|
|
Logs are located at:
|
|
- Linux: `/var/log/jellyfin/`
|
|
- Windows: `%PROGRAMDATA%\Jellyfin\Server\log\`
|
|
- Docker: `/config/log/`
|
|
|
|
Look for lines containing:
|
|
- `PostgreSQL connection:`
|
|
- `The database locking mode has been set to:`
|
|
- Database errors in the startup sequence
|
|
|
|
### Monitor PostgreSQL Logs
|
|
|
|
Enable query logging in `postgresql.conf`:
|
|
```
|
|
log_statement = 'all' # Log all queries (very verbose)
|
|
log_min_duration_statement = 1000 # Log queries taking > 1 second
|
|
```
|
|
|
|
Then check PostgreSQL logs:
|
|
- Linux: `/var/log/postgresql/`
|
|
- Windows: `%PROGRAMDATA%\PostgreSQL\<version>\data\log\`
|
|
|
|
## Common Configuration Mistakes
|
|
|
|
### 1. Wrong Locking Behavior
|
|
❌ **Don't use:**
|
|
```xml
|
|
<LockingBehavior>Pessimistic</LockingBehavior>
|
|
```
|
|
|
|
✅ **Use instead:**
|
|
```xml
|
|
<LockingBehavior>NoLock</LockingBehavior>
|
|
```
|
|
|
|
### 2. Missing CustomProviderOptions
|
|
PostgreSQL requires `CustomProviderOptions` even though it's now a built-in provider (for backward compatibility).
|
|
|
|
### 3. Incorrect Port Format
|
|
❌ **Wrong:**
|
|
```xml
|
|
<Value>postgresql://localhost:5432</Value>
|
|
```
|
|
|
|
✅ **Correct:**
|
|
```xml
|
|
<CustomDatabaseOption>
|
|
<Key>host</Key>
|
|
<Value>localhost</Value>
|
|
</CustomDatabaseOption>
|
|
<CustomDatabaseOption>
|
|
<Key>port</Key>
|
|
<Value>5432</Value>
|
|
</CustomDatabaseOption>
|
|
```
|
|
|
|
## Recovery Steps
|
|
|
|
If Jellyfin won't start due to database issues:
|
|
|
|
1. **Stop Jellyfin**
|
|
|
|
2. **Backup Current Configuration**
|
|
```bash
|
|
cp config/database.xml config/database.xml.backup
|
|
```
|
|
|
|
3. **Switch Back to SQLite** (temporary):
|
|
```xml
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
<DatabaseConfigurationOptions>
|
|
<DatabaseType>Jellyfin-SQLite</DatabaseType>
|
|
<LockingBehavior>NoLock</LockingBehavior>
|
|
</DatabaseConfigurationOptions>
|
|
```
|
|
|
|
4. **Restart Jellyfin** and verify it works
|
|
|
|
5. **Fix PostgreSQL configuration** and try again
|
|
|
|
## Getting Help
|
|
|
|
If you're still experiencing issues:
|
|
|
|
1. Enable detailed logging (see Debugging section above)
|
|
2. Collect logs from both Jellyfin and PostgreSQL
|
|
3. Note your configuration (without password)
|
|
4. Check Jellyfin forums/GitHub issues with:
|
|
- Error messages
|
|
- PostgreSQL version
|
|
- Jellyfin version
|
|
- Operating system
|