python / expert
Snippet
Unterbrechungsfreie Datenbank-Index-Migrationen ohne Ausfallzeiten in Django
Standard-Django-Indexmigrationen sperren Tabellen während der Ausführung und blockieren Schreibzugriffe in Produktionsumgebungen. Eine eigene nicht-atomare Migrations-`Operation` führt `CREATE INDEX CONCURRENTLY` in PostgreSQL ohne Sperren der Schreibverbindungen aus.
snippet.py
python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from django.db.migrations.operations.base import Operationclass AddConcurrentIndex(Operation):atomic = Falsedef __init__(self, model_name: str, index_name: str, columns: list[str]):self.model_name = model_nameself.index_name = index_nameself.columns = columnsdef database_forwards(self, app_label, schema_editor, from_state, to_state):if schema_editor.connection.vendor == 'postgresql':table_name = f"{app_label}_{self.model_name.lower()}"cols = ", ".join(self.columns)sql = f"CREATE INDEX CONCURRENTLY IF NOT EXISTS {self.index_name} ON {table_name} ({cols});"schema_editor.execute(sql)def database_backwards(self, app_label, schema_editor, from_state, to_state):if schema_editor.connection.vendor == 'postgresql':sql = f"DROP INDEX CONCURRENTLY IF NOT EXISTS {self.index_name};"schema_editor.execute(sql)
django
Erklärung
1
atomic = False
Teilt dem Migration-Framework mit, dass diese Operation außerhalb von globale SQL-Transaktionsblöcken laufen muss.
2
sql = f"CREATE INDEX CONCURRENTLY IF NOT EXISTS ..."
Führt die konkurrierende Erstellung des PostgreSQL-Index ohne exklusive Schreibsperren auf der Tabelle aus.
3
def database_backwards(self, app_label, schema_editor, from_state, to_state):
Definiert die Rückgängerungslogik (Rollback) zum Entfernen des Indexes bei einer Migrations-Rückabwicklung.