Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Az SQL Serverhez és az Azure SQL-hez való kapcsolatok a kódjától független okok miatt átmenetileg meghiúsulhatnak:
- Az Always On rendelkezésre állási csoport feladatátvételt hajt végre.
- A hálózat a kapcsolat beállítása során elvet egy csomagot.
- A Resource Governor korlátozza az adatbázist.
- A Azure SQL replika skálázás vagy frissítés során lesz újrahasznosítva.
A hibák többsége másodperceken belül törlődik. Ez a cikk bemutatja, hogyan lehet újrapróbálni átmeneti hibák esetén egy mssql-django háttérrendszert használó Django-alkalmazásban, és hogyan konfigurálható a Django és az ODBC-illesztő úgy, hogy automatikusan helyreálljanak a tétlen kapcsolatok megszakadása után.
Átmeneti hibák
Az átmeneti hibák átmeneti hibák, amelyek önállóan oldódnak meg. A művelet rövid késleltetés után történő újrapróbálkozása általában sikeres lesz.
A következő hibák átmenetiek, amikor a kapcsolat létrehozásakor vagy a kiszolgálónak küldött kérések során fordulnak elő. Próbálkozzon újra rövid, korlátozott várakozási idő után. A néhány újrapróbálkozást követő hibák általában olyan konfigurációs problémát jeleznek (hibás kiszolgáló, hiányzó engedélyek, kimerült kvóta), amely az újrapróbálkozást nem oldja meg.
| Hiba | Message | Troubleshooting |
|---|---|---|
64 |
A connection was successfully established with the server, but then an error occurred during the login process. (provider: TCP Provider, error: 0 - The specified network name is no longer available.) |
A TCP-kapcsolat kézfogás közben megszakad. Ez nem hitelesítési hiba. Ha továbbra is fennáll, ellenőrizze az ügyféloldali hálózati instabilitást, vagy egy olyan köztes eszközt, amely megszakítja a félig létrehozott kapcsolatokat. |
233 |
The client was unable to establish a connection because of an error during connection initialization process before login. |
Bejelentkezés előtti átvitel vagy TLS-hiba. A kiszolgáló általában akkor adja vissza, ha nem tudja elfogadni a kapcsolatot (erőforrás-kimerültség, elért maximális kapcsolatok vagy nem támogatott ügyfél). Ez nem hitelesítési hiba. Ellenőrizze a kiszolgáló állapotát, majd ellenőrizze az ügyfél bejelentkezési időtúllépését, a TLS-beállításokat és az ügyfél/kiszolgáló TLS-verziókompatibilitását. |
4060 |
Cannot open database "%.*ls" requested by the login. The login failed. |
A bejelentkezés hitelesít, de nem tudja megnyitni a kért adatbázist. Az átmeneti okok közé tartozik, ha az adatbázis átmeneti állapotban van (feladatátvétel, visszaállítás, skálázás miatt), vagy automatikusan szüneteltetve van. Az állandó okok (az adatbázis nem létezik, a bejelentkezés nem rendelkezik hozzáféréssel) nem lesznek javítva újrapróbálkozással; ellenőrizze az adatbázis nevét, a bejelentkezési leképezést és az adatbázis állapotát. |
4221 |
Login to read-secondary failed due to long wait on 'HADR_DATABASE_WAIT_FOR_TRANSITION_TO_VERSIONING'. |
A replika nem érhető el bejelentkezéshez, mert a sorverziók hiányoznak a replika újrafeldolgozásakor repülés közben végrehajtott tranzakciókhoz. A probléma megoldásához vonja vissza vagy véglegesítse az aktív tranzakciókat az elsődleges kiszolgálón. Csökkentse ezt azzal, hogy kerüli a hosszú írási tranzakciókat az elsődleges csomóponton. |
10053 |
A transport-level error has occurred when sending the request to the server. (provider: TCP Provider, error: 0 - An established connection was aborted by the software in your host machine.) |
A helyi oldal megszakítja a kapcsolatot. Ellenőrizze az ügyféloldali hálózat állapotát, valamint a helyi tűzfal vagy VPN-ügyfél állapotát. |
10054 |
A transport-level error has occurred when sending the request to the server. (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.) |
A távoli oldal TCP-alaphelyzetbe állítást küld. Gyakori okok: a partnerfolyamat összeomlott, egy tűzfal resetet küldött, vagy az Azure SQL-átjáró lezárt egy inaktív kapcsolatot. Tétlenség miatti kapcsolatbontási minták esetén engedélyezze a TCP keepalive funkciót az ügyféloldalon, vagy csökkentse a kapcsolatpool tétlenségi időkorlátját. |
10928 |
Resource ID: %d. The %s limit for the database is %d and has been reached. See 'http://go.microsoft.com/fwlink/?LinkId=267637' for assistance. |
Az adatbázis túllépi a Azure SQL erőforrás-szabályozási korlátot. Az 1. erőforrás-azonosító a feldolgozói korlátot jelzi; A 2. erőforrás-azonosító a munkamenetkorlátot jelzi. Azonosítsa az üzenet korláttípusát, majd csökkentse az egyidejűséget, skálázza fel az adatbázist, vagy lerövidítse az erőforrást tartalmazó hosszú ideig futó műveleteket. |
10929 |
Resource ID: %d. The %s minimum guarantee is %d, maximum limit is %d, and the current usage for the database is %d. However, the server is currently too busy to support requests greater than %d for this database. |
Az adatbázis meghaladja a számára garantált minimumot, és a mögöttes kiszolgáló korlátozza a teljesítményét. Az újrapróbálkozás általában akkor sikeres, ha a szomszéd terhelés csökken. A tartós előfordulások azt jelzik, hogy magasabb szolgáltatási szintre vagy kevésbé zajos környezetre van szüksége. |
40020, 40143, 4016640540 |
Error code %d A 40197-es hibahelyen jelentve a feladatátvétel során. |
A 40197-es feladatátvételi üzenetbe beágyazott alkódok, amelyek egyes útvonalakon legfelső szintű hibaszámként jelennek meg. Kezelje őket ugyanúgy, mint a 40197-et. |
40197 |
The service has encountered an error processing your request. Please try again. Error code %d. |
Szoftverfrissítés, hardverhiba vagy más feladatátvételi esemény az Azure SQL-ben. Az újracsatlakozás egy működőképes replikához kapcsol. A beágyazott hibakód azonosítja a feladatátvétel típusát. Ha a hiba továbbra is fennáll, rögzítse a munkamenet-nyomkövetés azonosítóját, és forduljon az ügyfélszolgálathoz. |
40501 |
The service is currently busy. Retry the request after 10 seconds. Incident ID: %ls. Code: %d. |
Azure SQL motor szabályozása. Az ajánlott minimális várakozási idő 10 másodperc. A tartós korlátozás azt jelzi, hogy a munkaterhelés túllépte az adatbázis erőforrás-kiosztását; növelje a szolgáltatási szintet, vagy csökkentse a párhuzamosságot. |
40613 |
Database '%.*ls' on server '%.*ls' is not currently available. Please retry the connection later. If the problem persists, contact customer support, and provide them with the session tracing ID of '%.*ls'. |
Az adatbázis nem érhető el, általában feladatátvétel alatt vagy rövid ideig egy skálázási művelet közben. Próbálkozzon újra egy visszalépéssel; ha néhány perc elteltével is megmarad, rögzítse a munkamenet nyomkövetési azonosítóját, és nyisson meg egy támogatási esetet. |
42108 |
Can not connect to the SQL pool since it is paused. Please resume the SQL pool and try again. |
A dedikált SQL-készlet (Synapse) szüneteltetett állapotban van. Az újrapróbálás csak a készlet újraindítása után sikerül. Állítsa vissza explicit módon a készletet működő állapotba, vagy ütemezze a munkaterhelés futtatását a készlet folytatását követő időpontra. |
42109 |
The SQL pool is warming up. Please try again. |
A dedikált SQL-készlet újra működik. Próbálkozzon újra egyre hosszabb várakozási időkkel, amíg a pool online nem lesz; a bemelegítés általában néhány percet vesz igénybe. |
49918 |
Cannot process request. Not enough resources to process request. The service is currently busy. Please retry the request later. |
A kiszolgáló jelenleg nem tud elegendő erőforrást lefoglalni a kérés teljesítéséhez. Próbálkozzon újra egy visszalépéssel. Ha a hiba továbbra is fennáll, skálázza fel az adatbázist vagy a rugalmas készletet. |
49919 |
Cannot process create or update request. Too many create or update operations in progress for subscription "%ld". |
Előfizetési szintű egyidejűségi korlát a felügyeleti műveletekre. Csökkentse a párhuzamos létrehozási vagy frissítési hívások számát, vagy időben tolja el őket. |
49920 |
Cannot process request. Too many operations in progress for subscription "%ld". |
Előfizetésszintű egyidejűségi korlát a repülési műveletekre. Csökkentse a párhuzamosságot, vagy várja meg, amíg a folyamatban lévő műveletek befejeződnek. |
Az utasításszintű hibák nem szerepelnek ezen a listán, mert a kapcsolat létrejötte után jelentkeznek, és a hiba ellenére a munkamenet továbbra is használható marad. A leggyakoribb újrapróbálkozható utasításhibák az 1205 (holtpont áldozata) és az 1222 (zárolási kérelem időtúllépése). Az egyetlen sikertelen utasítás helyett próbálkozzon újra a teljes tranzakcióval.
A hibaüzenet szövege Azure SQL átmeneti kapcsolati hibákból származik. Az egyes illesztőprogramok saját beépített újrapróbálkozási listákat tartanak fenn; ez a katalógus azt írja le, hogy mely hibák alkalmasak az újrapróbálkozásra az SQL Server, az Azure SQL Database, az Azure SQL Managed Instance, a Microsoft Fabric SQL-adatbázisa és az Azure Synapse Analytics dedikált SQL-készletei esetén.
Az ODBC-illesztőprogram üresjárati kapcsolatainak hibatűrése
A Microsoft SQL Serverhez készült ODBC-illesztőprogram beépített helyreállítási képességet biztosít az inaktív kapcsolatokhoz a ConnectRetryCount kapcsolati sztring ConnectRetryInterval kulcsszavaival. Ezek a beállítások az inaktív, megszakadt kapcsolatokat az illesztőprogram szintjén kezelik, még mielőtt az alkalmazás kódja érintetté válna.
Az üresjárati kapcsolatok hibaállóságának engedélyezése a(z) extra_params esetében:
DATABASES = {
"default": {
"ENGINE": "mssql",
"NAME": "<your-database>",
"HOST": "<your-server>.database.windows.net",
"PORT": "1433",
"OPTIONS": {
"driver": "ODBC Driver 18 for SQL Server",
"extra_params": "ConnectRetryCount=3;ConnectRetryInterval=10",
},
},
}
| Keyword | Alapértelmezett | Description |
|---|---|---|
ConnectRetryCount |
1 | Tétlen kapcsolatok automatikus újracsatlakozási kísérleteinek száma. |
ConnectRetryInterval |
10 | Másodperc az újracsatlakozási kísérletek között. |
Note
Az inaktív kapcsolat rugalmassága újracsatlakoztat olyan kapcsolatokat, amelyek tétlen állapotban megszakadtak. Nem próbálkozik újra a sikertelen lekérdezésekkel, és nem áll helyre az aktív tranzakciók során előforduló hibákból. Ezekben a forgatókönyvekben használja az alkalmazásszintű újrapróbálkozás logikáját.
Django adatbázis köztes szoftver újrapróbálkozáshoz
Hozzon létre egy Django köztes szoftvert, amely észleli az átmeneti hibákat, és újrapróbálkozza az adatbázis-műveletet. Ez a megközelítés a nézetszintű kérések kezelésére használható:
# myproject/middleware.py
import random
import re
import time
import logging
from django.db import OperationalError, connection
logger = logging.getLogger(__name__)
TRANSIENT_ERROR_CODES = {
"64", "233", "4221",
"10053", "10054", "10928", "10929",
"40197", "40501", "40613",
"49918", "49919", "49920",
# Include "4060" only if targeting Azure SQL with geo-replication failover.
# It is usually a permanent error (wrong database name or missing permissions).
}
# Microsoft ODBC driver formats native error codes as "(<number>)" in the
# message. Extracting parenthesized codes avoids false positives that a plain
# substring match would produce for short codes like "64".
_CODE_RE = re.compile(r"\((\d+)\)")
def is_transient(error):
codes_in_message = set(_CODE_RE.findall(str(error)))
return bool(codes_in_message & TRANSIENT_ERROR_CODES)
class DatabaseRetryMiddleware:
"""Retry database operations on transient errors."""
def __init__(self, get_response):
self.get_response = get_response
self.max_retries = 3
self.base_delay = 1 # seconds; doubled each attempt
self.max_delay = 30 # cap on a single sleep, regardless of attempt
def __call__(self, request):
for attempt in range(self.max_retries + 1):
try:
return self.get_response(request)
except OperationalError as e:
if attempt < self.max_retries and is_transient(e):
# Exponential backoff with full jitter, capped at max_delay.
# Jitter spreads simultaneous retries so many clients
# don't hammer the server in lock-step during an outage.
capped = min(self.max_delay, self.base_delay * (2 ** attempt))
delay = random.uniform(0, capped)
logger.warning(
"Transient DB error (attempt %d/%d), retrying in %.2fs: %s",
attempt + 1, self.max_retries, delay, e
)
connection.close()
time.sleep(delay)
continue
raise
A köztes szoftver regisztrálása a következő helyen settings.py:
MIDDLEWARE = [
"myproject.middleware.DatabaseRetryMiddleware",
"django.middleware.security.SecurityMiddleware",
# ... other middleware
]
Important
Helyezze az DatabaseRetryMiddleware adatbázist elérő többi köztes szoftver elé, hogy észlelhesse és újrapróbálkozhassa a teljes kérelemfolyamat átmeneti hibáit.
Dekorátor újrapróbálkozása adott műveletekhez
A finomabb szabályozáshoz használjon dekorátort az egyes funkciókhoz:
import random
import re
import time
import functools
import logging
from django.db import OperationalError, connection
logger = logging.getLogger(__name__)
TRANSIENT_ERROR_CODES = {
"64", "233", "4221",
"10053", "10054", "10928", "10929",
"40197", "40501", "40613",
"49918", "49919", "49920",
# Include "4060" only if targeting Azure SQL with geo-replication failover.
}
_CODE_RE = re.compile(r"\((\d+)\)")
def is_transient(error):
codes_in_message = set(_CODE_RE.findall(str(error)))
return bool(codes_in_message & TRANSIENT_ERROR_CODES)
def retry_on_transient(max_retries=3, base_delay=1, max_delay=30):
"""Retry on transient database errors with exponential backoff and full jitter."""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(max_retries + 1):
try:
return func(*args, **kwargs)
except OperationalError as e:
if attempt < max_retries and is_transient(e):
# Exponential cap doubled per attempt, then jittered
# within [0, cap] and limited by max_delay.
capped = min(max_delay, base_delay * (2 ** attempt))
delay = random.uniform(0, capped)
logger.warning(
"Transient error in %s (attempt %d/%d), retrying in %.2fs: %s",
func.__name__, attempt + 1, max_retries, delay, e
)
connection.close()
time.sleep(delay)
continue
raise
return wrapper
return decorator
Alkalmazza a dekoratőrt az adatbázis-nehéz függvényekre:
from myproject.retry import retry_on_transient
@retry_on_transient(max_retries=3, base_delay=2)
def process_order(order_id):
"""Process an order with automatic retry on transient failures."""
order = Order.objects.select_for_update().get(id=order_id)
order.status = "processing"
order.save()
return order
Újrapróbálkozás tranzakciókkal
Ha egy tranzakción belül átmeneti hiba történik, a kiszolgáló visszaállítja a teljes tranzakciót. Próbálja újra a teljes tranzakciót, ne csak a sikertelen utasítást:
from django.db import transaction
@retry_on_transient(max_retries=3)
def transfer_funds(from_account_id, to_account_id, amount):
"""Transfer funds between accounts with retry."""
with transaction.atomic():
from_account = Account.objects.select_for_update().get(id=from_account_id)
to_account = Account.objects.select_for_update().get(id=to_account_id)
from_account.balance -= amount
to_account.balance += amount
from_account.save()
to_account.save()
Caution
Ne próbálkozzon újra a(z) transaction.atomic() elemen belül. Az újrapróbálkozást indító dekorátornak a teljes atomic() blokkot be kell burkolnia, hogy minden újrapróbálkozás új tranzakciót indukáljon.
Utasításszintű hibák
Az előző szakaszban található hibalista a kapcsolatszintű hibákat ismerteti. Két másik hibát is gyakran újrapróbálnak utasításszinten:
- 1205: A munkamenet holtpont áldozatául lett kiválasztva. Ismételje meg a tranzakciót.
-
1222: A zárolási kérelem időtúllépése lejárt. Futtassa újra a tranzakciót, vagy növelje a
LOCK_TIMEOUTértékét ennél a munkamenetnél, ha az alapértelmezett érték túl agresszív.
ConnectRetryCount automatikusan újrapróbálkozik megszakadt kapcsolatok esetén, így ez nem vonatkozik ezekre az utasításszintű hibákra. Kezelje ezeket ugyanazzal a dekorátormintával úgy, hogy a biztonságosan újrafuttatható tranzakciókhoz hozzáadja a(z) "1205" és "1222" elemeket a(z) TRANSIENT_ERROR_CODES elemhez.
CONN_MAX_AGE és elavult kapcsolatok
A Django újra felhasználja az adatbázis-kapcsolatokat a kérések között, amikor CONN_MAX_AGE be van állítva. A hosszú élettartamú kapcsolatok elavulttá válhatnak, ha a kiszolgáló bezárja azt (például egy Azure SQL skálázási művelet vagy egy tűzfal időtúllépése során).
Állítsa be az újrahasználat és az elavultság egyensúlyának beállítását CONN_MAX_AGE :
DATABASES = {
"default": {
"ENGINE": "mssql",
"NAME": "<your-database>",
"HOST": "<your-server>.database.windows.net",
"OPTIONS": {
"driver": "ODBC Driver 18 for SQL Server",
},
"CONN_MAX_AGE": 600, # Close and reopen connections after 10 minutes
},
}
-
CONN_MAX_AGE=0(alapértelmezett): Zárja be a kapcsolatot az egyes kérések végén. Legbiztonságosabb, de leglassabb. -
CONN_MAX_AGE=600: 10 percig újra felhasználhatja a kapcsolatokat. Jó egyensúly a legtöbb webalkalmazás számára. -
CONN_MAX_AGE=None: A kapcsolatok határozatlan ideig nyitva maradnak. Csak az elavult kapcsolatok újrapróbálkozási mechanizmusával használható.
CONN_HEALTH_CHECKS (Django 4.1 és újabb verziók)
Bevezettük CONN_HEALTH_CHECKSa Django 4.1-et, amely minden kérés előtt ellenőrzi az újrahasznált kapcsolatot. Engedélyezze a(z) CONN_MAX_AGE mellett az elavult kapcsolatok automatikus észlelését:
DATABASES = {
"default": {
"ENGINE": "mssql",
"NAME": "<your-database>",
"HOST": "<your-server>.database.windows.net",
"OPTIONS": {
"driver": "ODBC Driver 18 for SQL Server",
},
"CONN_MAX_AGE": 600,
"CONN_HEALTH_CHECKS": True,
},
}
Ha engedélyezve van az állapot-ellenőrzés, a Django egy egyszerű érvényesítési lekérdezést ad ki a kapcsolat újbóli használata előtt. Ha a kapcsolat megszakadt, a Django transzparensen megnyit egy újat ahelyett, hogy hibát jelezne.
Bevált gyakorlatok
- Használjon exponenciális visszalépést teljes jitterrel. Duplázza meg a felső határt minden kísérletnél, majd várakozzon egy véletlenszerű ideig a
[0, cap]intervallumon belül. A véletlenszerű késleltetés megakadályozza, hogy sok ügyfél egy regionális szolgáltatáskimaradás során egyszerre próbálkozzon újra, ami egyébként egy rövid ideig tartó hibát tartós túlterheléssé alakíthat. A kísérletenkénti alvó állapotot (például 30 másodpercet) korlátozza, így a teljes helyreállítási idő korlátozott marad. - Állítsa be az újrapróbálkozás felső határát. Három, exponenciális visszalépéssel végzett újrapróbálkozás ésszerű alapértelmezett érték. Több mint öt újrapróbálkozás általában nem átmeneti problémát jelez.
- Az újrapróbálkozás előtt zárja be a kapcsolatot. Hívja meg
connection.close(), hogy Django új kapcsolatot létesítsen a következő kísérlet során. - Minden újrapróbálkozás naplózása. A csendesen sikeres újrapróbálkozások elrejthetik a teljesítményproblémákat. Jelentkezzen be a
WARNINGszinten, hogy nyomon tudja követni a gyakoriságot. - Ne próbálja újra a nem átmeneti hibák esetén. A hitelesítési hibák, az engedélyhibák és a szintaxishibák nem hasznosak az újrapróbálkozásokban.
- Próbálkozzon újra a teljes tranzakcióval. Foglalja a(z)
transaction.atomic()elemet az újrapróbálkozási logikába, ne fordítva. -
Engedélyezi
CONN_HEALTH_CHECKS(Django 4.1 és újabb verziók) azokat a webalkalmazásokat, amelyek használjákCONN_MAX_AGE.