Migrace aplikací Django z jiných databází do SQL Server

Tento článek obsahuje pokyny k migraci aplikací Django z PostgreSQL, MySQL nebo SQLite na SQL Server pomocí back-endumssql-django.

Overview

Django orM abstrahuje většinu rozdílů v databázi, ale některé chování a dialekty SQL se mezi back-endy liší. Tato příručka popisuje hlavní rozdíly, se kterými se setkáte při migraci na SQL Server.

Krok 1: Instalace mssql-django

mssql-django Nainstalujte balíček a jeho závislosti:

pip install mssql-django

Ujistěte se, že je nainstalovaný ovladač MICROSOFT ODBC pro SQL Server. Pokyny pro konkrétní platformu najdete v tématu Instalace mssql-django .

Krok 2: Aktualizace DATABASE konfigurace

Nahraďte stávající konfiguraci databáze v settings.py:

# Example: From PostgreSQL
# DATABASES = {
#     "default": {
#         "ENGINE": "django.db.backends.postgresql",
#         "NAME": "mydb",
#     },
# }

# To SQL Server
DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "USER": "<your-username>",
        "PASSWORD": "<your-password>",
        "HOST": "<your-server>",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
        },
    },
}

Krok 3: Vytvoření nových migrací

Začněte čistou historií migrace pro SQL Server:

# Remove existing migration files (keep __init__.py)
# Then regenerate
python manage.py makemigrations
python manage.py migrate

Important

Přenos dat pomocí migrace dat nebo samostatného procesu ETL Nepokoušejte se spustit soubory migrace PostgreSQL nebo MySQL na SQL Server.

Klíčové rozdíly oproti PostgreSQL

Vlastnost PostgreSQL SQL Server (mssql-django)
Automatické zvyšování SERIAL / BIGSERIAL IDENTITY(1,1)
Booleovský (logický) typ Nativní boolean bit (0 nebo 1)
Textová pole text (bez omezení) nvarchar(max)
Podpora JSON Původní jsonb nvarchar(max) s funkcemi JSON (SQL Server 2016+)
Pole polí ArrayField Není podporováno. Použijte související tabulku nebo JSON.
Pole typu HStore HStoreField Není podporováno. Místo toho použijte JSONField.
Pole rozsahu hodnot IntegerRangeField, BigIntegerRangeField, , DateRangeFieldDateTimeRangeField Není podporováno. Použijte dvě samostatná pole.
Fulltextové vyhledávání SearchVector, SearchRank Používejte nezpracované příkazy SQL s fulltextovým vyhledáváním SQL Serveru.
DISTINCT ON Podporováno Není podporováno. Použijte GROUP BY nebo poddotazy.
DateTimeField s časovým pásmem timestamp with time zone datetimeoffset (when USE_TZ=True) nebo datetime2

Funkce specifické pro PostgreSQL, které se mají nahradit

Pokud váš kód používá prvky specifické pro PostgreSQL z django.contrib.postgres, nahraďte je:

# PostgreSQL ArrayField - replace with JSONField or related table
# Before
from django.contrib.postgres.fields import ArrayField
tags = ArrayField(models.CharField(max_length=50))

# After (using JSONField)
tags = models.JSONField(default=list)

# PostgreSQL HStoreField - replace with JSONField
# Before
from django.contrib.postgres.fields import HStoreField
metadata = HStoreField()

# After
metadata = models.JSONField(default=dict)

Hlavní rozdíly oproti MySQL

Vlastnost MySQL SQL Server (mssql-django)
Automatické zvyšování AUTO_INCREMENT IDENTITY(1,1)
Booleovský (logický) typ tinyint(1) bit
Textová pole longtext nvarchar(max)
Podpora JSON Nativní JSON (5.7 a novější verze) nvarchar(max) s funkcemi JSON
Collation Konfigurovatelné pro jednotlivé sloupce Na úrovni instance nebo databáze (lze přepsat pomocí volby COLLATE)
DateTimeField datetime(6) datetimeoffset nebo datetime2

Hlavní rozdíly od SQLite

Vlastnost SQLite SQL Server (mssql-django)
Vynucení typů Flexibilní psaní Vynucení striktního typu
Souběžné zápisy Limited Úplná podpora souběžnosti
Maximální počet připojení Prakticky 1 zapisovač Sdružování připojení s mnoha souběžnými připojeními
DateTimeField Uloženo jako text datetimeoffset nebo datetime2

Rozdíly třídění

Řazení určuje, jakým způsobem SQL Server porovnává a řadí text. Toto je jeden z nejběžnějších zdrojů neočekávaného chování při migraci z PostgreSQL nebo MySQL.

Citlivost na velikost písmen

Výchozí kolace serveru SQL Server (SQL_Latin1_General_CP1_CI_AS) nerozlišuje malá a velká písmena. Ve výchozím nastavení PostgreSQL rozlišuje malá a velká písmena.

Toto chování znamená, že po migraci se dotazy, které dříve rozlišovaly, "Smith" a "smith" považují je za stejné:

# On PostgreSQL: returns only exact case matches
# On SQL Server (default collation): returns both "Smith" and "smith"
User.objects.filter(last_name="Smith")

Pokud vaše aplikace závisí na porovnáních s rozlišováním velkých a malých písmen, máte dvě možnosti:

  • Změňte kolaci databáze nebo sloupce na variantu s rozlišováním velkých a malých písmen:

    -- Database-level (affects all new columns)
    ALTER DATABASE [<your-database>] COLLATE Latin1_General_CS_AS;
    
    -- Column-level (for specific columns)
    ALTER TABLE [<your-table>]
    ALTER COLUMN [<column-name>] NVARCHAR (150) COLLATE Latin1_General_CS_AS;
    
  • Použijte vyhledávání v Djangu __exact s přepsáním pravidel řazení v nezpracovaném SQL pro cílené dotazy.

Zvýraznění citlivosti

Výchozí kolace serveru SQL Server rozlišuje akcenty (AS), což odpovídá chování PostgreSQL. Znaky jako é a e jsou považovány za odlišné. Pokud potřebujete porovnání nerozlišující zvýraznění, použijte kolaci končící na _AI.

Nastavení řazení v mssql-django

Přepište výchozí řazení pro vyhledávání v textových polích ve vaší konfiguraci databáze:

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "<your-database>",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "collation": "Latin1_General_CS_AS",  # Case-sensitive
        },
    },
}

Note

Možnost collation v mssql-django určuje kolaci používanou v LIKE a v operacích porovnání generovaných vyhledáváními ORM frameworku Django. Nemění kolaci existujících sloupců v databázi. Pokud chcete změnit kolaci uložených sloupců, použijte ALTER TABLE / ALTER COLUMN příkazy. Další informace naleznete v dokumentaci ke kolacím v SQL Serveru.

Krok 4: Aktualizace vlastního SQL

Pokud váš kód obsahuje nezpracovaný SQL, aktualizujte ho na syntaxi SQL Server:

# PostgreSQL syntax
# cursor.execute("SELECT * FROM products LIMIT 10 OFFSET 20")

# SQL Server syntax
cursor.execute("SELECT * FROM products ORDER BY id OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY")

Běžné rozdíly syntaxe SQL:

Operation PostgreSQL/MySQL SQL Server
Omezit výsledky LIMIT 10 TOP 10 nebo OFFSET ... FETCH NEXT ...
Zřetězení řetězců \|\| (PG) / CONCAT() + nebo CONCAT()
Logické literály TRUE / FALSE 1 / 0
Aktuální časové razítko NOW() GETDATE(), SYSDATETIME()nebo SYSDATETIMEOFFSET() pro hodnoty s podporou časového pásma
POKUD NEEXISTUJE CREATE TABLE IF NOT EXISTS Zkontrolujte sys.objects nebo použijte IF NOT EXISTS

Rozdíly v izolaci transakcí

PostgreSQL používá pro svou READ COMMITTED úroveň izolace MVCC (Řízení souběžnosti více verzí). Čtenáři nikdy neblokují spisovatele a spisovatele nikdy blokují čtenáře.

Výchozí READ COMMITTED SQL Serveru používá zamykání, což znamená, že dotazy pro čtení můžou být blokované při čekání na dokončení transakcí zápisu. Pokud vaše aplikace po migraci zaznamenává zvýšené blokování, zvažte povolení READ COMMITTED SNAPSHOT v databázi:

ALTER DATABASE [<your-database>]
SET READ_COMMITTED_SNAPSHOT ON;

Tato změna způsobí, že SQL Server READ COMMITTED bude používat verzování řádků (podobně jako MVCC v PostgreSQL) namísto zamykání. Čtenáři uvidí poslední potvrzenou verzi řádku bez čekání na aktivní zapisovače.

Note

READ COMMITTED SNAPSHOT vyžaduje další tempdb místo pro verze řádků. Před povolením v produkčním prostředí otestujte reálné zatížení. Další informace naleznete v tématu Správa transakcí v mssql-django.

Krok 5: Migrace dat

Strategie migrace dat závisí na velikosti datové sady:

Malé datové sady (<500 MB)

Použijte Django dumpdata/loaddata:

# On the source database
python manage.py dumpdata --natural-foreign --natural-primary -o data.json

# Switch settings.py to SQL Server, then:
python manage.py migrate
python manage.py loaddata data.json

Velké datové sady (>500 MB)

Pro velké migrace použijte specializované nástroje, které zabrání problémům s vyčerpáním paměti a vypršením časového limitu. ORM v Djangu není pro hromadné zpracování dat v tomto rozsahu vhodným nástrojem. Obejít ho pro přesun dat a nechat Django spravovat schéma a aplikační logiku poté.

Tool Nejlepší pro
Průvodce importem a exportem SQL Serveru Migrace z místního prostředí do místního prostředí s grafickým uživatelským rozhraním
Azure Data Factory Z libovolného zdroje do Azure SQL, včetně hybridních scénářů
Azure Database Migration Service Rozsáhlé migrace s integrovaným ověřováním a vrácením zpět
Hromadné kopírování mssql-python pomocí Apache Arrow Vlastní kanály Python, které potřebují maximální propustnost mezi SQL Server, Azure SQL Database a databází SQL v Fabric

Ověření po migraci

Po migraci ověřte konzistenci počátečních dat identity pro sloupce automatického přírůstku:

-- Check identity seed and current value for all tables
SELECT 
    TABLE_NAME,
    IDENT_SEED(TABLE_SCHEMA + '.' + TABLE_NAME) AS IdentitySeed,
    IDENT_INCR(TABLE_SCHEMA + '.' + TABLE_NAME) AS IdentityIncrement,
    IDENT_CURRENT(TABLE_SCHEMA + '.' + TABLE_NAME) AS CurrentIdentity
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
    AND OBJECTPROPERTY(OBJECT_ID(TABLE_SCHEMA + '.' + TABLE_NAME), 'TableHasIdentity') = 1
ORDER BY TABLE_NAME;

Pokud CurrentIdentity překročí IdentitySeed + record_count, znovu inicializovat:

DBCC CHECKIDENT ('your_table', RESEED, new_seed);