Rozwiązuj problem ze sterownikiem go-mssqldb

Ten artykuł zawiera rozwiązania typowych błędów i problemów z łącznością sterownika go-mssqldb .

Zacznij od najprostszych testów

Zanim włączysz szczegółowe rejestrowanie lub zmienisz ustawienia puli, zapoznaj się z poniższą listą:

  1. Sprawdź podstawową dostępność: nazwę serwera, port, reguły zapory oraz czy SQL Server czy Azure SQL akceptuje połączenia.
  2. Weryfikuj dane uwierzytelniające: nazwa sterownika, nazwa użytkownika, hasło, format domeny lub fedauth konfiguracja.
  3. Sprawdź ustawienia TLS: encrypt, ścieżki hostnameincertificatecertyfikatów , oraz czy TrustServerCertificate są odpowiednie dla danego środowiska.
  4. Dopiero po poprawnym skonfigurowaniu połączenia sprawdź wyczerpanie puli, przestarzałe połączenia, logikę powtórek oraz spowolnioną lub zablokowaną diagnostykę zapytań.

Skorzystaj z wczesnych sekcji tego artykułu na temat awarii konfiguracji połączenia. Korzystaj z dalszych sekcji dopiero wtedy, gdy połączenia przynajmniej czasami działają poprawnie, a następnie zaczynają zawodzić pod obciążeniem, po okresie bezczynności lub podczas przełączania awaryjnego.

Błędy połączenia

Poniższe sekcje omawiają typowe komunikaty o błędach związanych z połączeniem oraz ich rozwiązania.

Nie udało się otworzyć połączenia TCP

Komunikat o błędzie: unable to open tcp connection with host 'localhost:1433': dial tcp 127.0.0.1:1433: connectex: No connection could be made because the target machine actively refused it.

Przyczyny i rozwiązania:

  • SQL Server nie działa. Uruchom usługę SQL Server.
  • TCP/IP nie jest włączone. Otwórz SQL Server Configuration Manager i włącz TCP/IP w SQL Server> Protocols.
  • Zły port. Zweryfikowaj port w SQL Server Configuration Manager lub użyj SQL Server Browser dla nazwanych instancji.
  • Zapora sieciowa blokuje port. Dodaj regułę przychodzącą dla portu 1433 (lub skonfigurowanego portu).

Logowanie użytkownika nie powiodło się

Komunikat o błędzie: mssql: login error: Login failed for user '<user>'.

Przyczyny i rozwiązania:

  • Błędna nazwa użytkownika lub hasło. Zweryfikowaj dane uwierzytelniające.
  • Uwierzytelnianie SQL Server jest wyłączone. Włącz tryby uwierzytelniania SQL Server i Windows w właściwościach serwera.
  • Login nie istnieje. Utworz logowanie w SQL Server.
  • Login nie ma dostępu do docelowej bazy danych. Przyznaj dostęp do bazy danych za pomocą CREATE USER.

Błędy walidacji certyfikatów

Komunikat o błędzie: TLS Handshake failed: x509: certificate signed by unknown authority

Przyczyny i rozwiązania:

  • Serwer korzysta z certyfikatu podpisanego samodzielnie. Podaj ścieżkę certyfikatu za pomocą parametru certificate lub serverCertificate, albo ustaw TrustServerCertificate=true wyłącznie do celów programistycznych.
  • Certyfikat CA nie znajduje się w sklepie System Trust. Dodaj certyfikat CA do magazynu zaufania systemu operacyjnego lub określ go parametrem certificate .
  • Niezgodność nazwy hosta. Użyj hostnameincertificate, aby określić oczekiwaną nazwę w certyfikacie.

Więcej informacji można znaleźć w artykule Szyfrowanie i certyfikaty.

Upłynął limit czasu połączenia

Komunikat o błędzie: unable to open tcp connection with host '<server>:1433': dial tcp: i/o timeout

Przyczyny i rozwiązania:

  • Problemy z łącznością sieciową. Sprawdź, czy możesz połączyć się z serwerem, używając telnet <server> 1433 lub Test-NetConnection -ComputerName <server> -Port 1433.
  • Błąd rozwiązywania nazw DNS. Sprawdź, czy nazwa hosta jest poprawnie rozwiązana.
  • Zwiększ dial timeout lub connection timeout w parametrach połączenia.

Błędy uwierzytelniania

Poniższe sekcje dotyczą komunikatów o błędach uwierzytelniania.

Awarie uwierzytelniania NTLM

Komunikat o błędzie: NTLM authentication failed

Przyczyny i rozwiązania:

  • Nieprawidłowy format domeny. Zastosowanie DOMAIN\user w parametrze user id . W formacie URL zakoduj ukośnik wsteczny jako %5C.
  • Złe hasło. Sprawdź hasło do domeny.

Niepowodzenia uwierzytelniania protokołu Kerberos

Komunikat o błędzie: krb5: cannot resolve KDC for realm

Przyczyny i rozwiązania:

  • Brakuje lub jest źle skonfigurowana /etc/krb5.conf. Sprawdź, czy sekcja [realms] zawiera poprawny adres KDC dla Twojej domeny.
  • Brak ważnego biletu. Uruchom klist, aby sprawdzić, czy masz ważny bilet, albo uruchom kinit, aby go uzyskać.
  • Nie znaleziono pliku keytab. Zweryfikowaj ścieżkę w parametrze krb5-keytabfile .

Więcej informacji można znaleźć w sekcji SQL Server i Windows authentication.

Błędy uwierzytelniania Microsoft Entra ID

Komunikat o błędzie: clientCredentialFromCert: error reading certificate: ... lub DefaultAzureCredential: failed to acquire a token

Przyczyny i rozwiązania:

  • Nieprawidłowy identyfikator klienta, identyfikator najemcy lub sekret klienta. Zweryfikuj wartości w parametrach połączenia lub zmiennych środowiskowych.
  • Zarządzana tożsamość nie jest skonfigurowana na hostze. Zweryfikowaj tożsamość w portalu Azure.
  • Brakuje importu azuread paczki. Zaimportuj github.com/microsoft/go-mssqldb/azuread i użyj nazwy sterownika azuresql .

Aby uzyskać więcej informacji, zobacz Microsoft Entra ID authentication (Uwierzytelnianie za pomocą identyfikatora Entra firmy Microsoft).

Logowanie użytkownika '' nie powiodło się (pusta nazwa użytkownika)

Komunikat o błędzie: mssql: login error: Login failed for user ''.

Przyczyna: Używasz sql.Open("sqlserver", ...) z parametrem fedauth . Uwierzytelnianie Entra ID wymaga nazwy sterownika azuresql, zarejestrowanej przez pakiet azuread. W przypadku standardowego sterownika sqlserver parametr fedauth jest ignorowany, a sterownik próbuje przeprowadzić uwierzytelnianie SQL bez podania nazwy użytkownika.

Rozwiązanie: Importuj azuread pakiet i użyj nazwy sterownika azuresql :

import _ "github.com/microsoft/go-mssqldb/azuread"

db, err := sql.Open("azuresql",
    "sqlserver://<server>.database.windows.net?database=AdventureWorks2025&fedauth=ActiveDirectoryDefault&encrypt=true&TrustServerCertificate=false")
if err != nil {
    panic(err)
}

Aby uzyskać więcej informacji, zobacz Microsoft Entra ID authentication (Uwierzytelnianie za pomocą identyfikatora Entra firmy Microsoft).

Błędy zapytań

Poniższe sekcje dotyczą komunikatów o błędach wykonywania zapytań.

LastInsertId nie obsługiwany

Komunikat o błędzie: LastInsertId is not supported. Please use the OUTPUT clause or add 'select ID = convert(bigint, SCOPE_IDENTITY())' to the end of your query.

Rozwiązanie: Sterownik go-mssqldb nie obsługuje LastInsertId(). Użyj klauzuli OUTPUT lub zapytania SCOPE_IDENTITY() osobno.

Tabela tymczasowa nie znaleziona

Komunikat o błędzie: mssql: Invalid object name '#TempTable'.

Przyczyna: Tabele tymczasowe są przypisane do danego połączenia. Jeśli utworzysz tabelę tymczasową w jednym wywołaniu i odpytasz ją w innym, mogą one używać różnych połączeń z puli.

Rozwiązanie: Użyj db.Conn(ctx), aby przypiąć do jednego połączenia, lub wykonuj operacje w ramach transakcji.

Aby uzyskać więcej informacji, zobacz Procedury składowane.

Błędy Azure SQL

Poniższe sekcje dotyczą błędów specyficznych dla Azure SQL Database.

Numery błędów połączenia przejściowego

Użyj poniższej wspólnej listy jako punktu odniesienia dla przejściowych błędów podczas nawiązywania połączenia oraz awarii warstwy transportowej na ścieżce żądania, które kwalifikują się do ograniczonego ponawiania:

Następujące błędy są przejściowe, gdy występują podczas nawiązywania połączenia lub podczas wysyłania żądania do serwera. Ponów próbę na krótkim, ograniczonym wycofywaniu. Błędy, które utrzymują się po kilku ponownych próbach, zwykle wskazują problem z konfiguracją (niewłaściwy serwer, brakujące uprawnienia, wyczerpany limit przydziału), które ponawianie próby nie zostaną rozwiązane.

Error 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.) Połączenie TCP zostaje przerwane w trakcie negocjacji. To nie jest błąd poświadczenia. Jeśli problem będzie się powtarzał, sprawdź, czy po stronie klienta nie występuje niestabilność sieci lub czy urządzenie pośredniczące nie zrywa połączeń na wpół ustanowionych.
233 The client was unable to establish a connection because of an error during connection initialization process before login. Błąd transportu przed logowaniem lub błąd protokołu TLS. Serwer często zwraca go, gdy nie może zaakceptować połączenia (wyczerpanie zasobów, osiągnięto maksymalną liczbę połączeń lub nieobsługiwanego klienta). To nie jest błąd poświadczenia. Sprawdź kondycję serwera, a następnie sprawdź limit czasu logowania klienta, ustawienia protokołu TLS i zgodność wersji protokołu TLS klienta/serwera.
4060 Cannot open database "%.*ls" requested by the login. The login failed. Logowanie uwierzytelnia się, ale nie może otworzyć żądanej bazy danych. Przejściowe przyczyny obejmują sytuacje, w których baza danych jest w trakcie zmiany stanu (przełączenie awaryjne, przywracanie, skalowanie) lub została automatycznie wstrzymana. Trwałe przyczyny (baza danych nie istnieje, konto logowania nie ma dostępu) nie zostaną usunięte przez ponowienie próby; sprawdź nazwę bazy danych, mapowanie konta logowania oraz stan bazy danych.
4221 Login to read-secondary failed due to long wait on 'HADR_DATABASE_WAIT_FOR_TRANSITION_TO_VERSIONING'. Replika nie jest dostępna do logowania, ponieważ brakuje wersji wierszy dla transakcji, które były w locie podczas recyklingu repliki. Wycofaj lub zatwierdź aktywne transakcje na serwerze podstawowym, aby rozwiązać problem. Ogranicz to ryzyko, unikając długotrwałych transakcji zapisu na serwerze głównym.
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.) Strona lokalna zrywa połączenie. Sprawdź stan sieci po stronie klienta oraz lokalną zaporę lub klienta VPN.
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.) Po stronie zdalnej jest wysyłane resetowanie protokołu TCP. Typowe przyczyny: proces równorzędny uległ awarii, zapora wymusiła reset połączenia lub brama Azure SQL zamknęła bezczynne połączenie. W przypadku resetowania połączenia z powodu bezczynności włącz mechanizm TCP keepalive po stronie klienta lub skróć limit czasu bezczynności w puli połączeń.
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. Baza danych przekracza limit nadzoru nad zasobami Azure SQL. Identyfikator zasobu 1 oznacza limit procesów roboczych; identyfikator zasobu 2 oznacza limit sesji. Zidentyfikuj typ limitu na podstawie komunikatu, a następnie zmniejsz współbieżność, zwiększ zasoby bazy danych lub skróć długotrwałe operacje blokujące zasób.
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. Baza danych przekroczyła swoje minimalne gwarantowane zasoby, a serwer bazowy ogranicza jej wydajność. Ponowienie próby zwykle kończy się powodzeniem, gdy obciążenie sąsiada spadnie. Trwałe wystąpienia wskazują, że potrzebujesz wyższej warstwy usług lub mniej hałaśliwego środowiska.
40020, 40143, 40166, 40540 Zgłoszone w Error code %d miejscu błędu 40197 podczas pracy w trybie failover. Podkody osadzone w komunikacie failover 40197, które w niektórych ścieżkach wykonania są zwracane jako kod błędu najwyższego poziomu. Traktuj je tak samo jak 40197.
40197 The service has encountered an error processing your request. Please try again. Error code %d. Uaktualnienie oprogramowania, awaria sprzętu lub inne zdarzenie trybu failover w Azure SQL. Ponowne połączenie kieruje do sprawnej repliki. Wbudowany kod błędu identyfikuje typ przełączenia awaryjnego. Jeśli błąd będzie się powtarzać, przechwyć identyfikator śledzenia sesji i skontaktuj się z pomocą techniczną.
40501 The service is currently busy. Retry the request after 10 seconds. Incident ID: %ls. Code: %d. Ograniczanie silnika Azure SQL Zalecane minimalne opóźnienie wynosi 10 sekund. Długotrwałe ograniczanie wydajności wskazuje, że obciążenie przekroczyło przydzielone zasoby bazy danych; przejdź na wyższą warstwę usługi lub zmniejsz współbieżność.
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'. Baza danych jest niedostępna, zwykle w połowie trybu failover lub krótko podczas operacji skalowania. Ponów próbę po odczekaniu; jeśli problem będzie się utrzymywał dłużej niż kilka minut, zapisz identyfikator śledzenia sesji i otwórz zgłoszenie do działu pomocy technicznej.
42108 Can not connect to the SQL pool since it is paused. Please resume the SQL pool and try again. Dedykowana pula SQL (Synapse) jest wstrzymana. Ponowienie próby zakończy się powodzeniem dopiero po wznowieniu puli. Wznów pulę ręcznie lub zaplanuj uruchomienie obciążenia po wznowieniu puli.
42109 The SQL pool is warming up. Please try again. Dedykowana pula SQL jest wznawiana. Ponów próbę w przypadku wycofywania, dopóki pula nie będzie w trybie online; rozgrzewka zwykle trwa kilka minut.
49918 Cannot process request. Not enough resources to process request. The service is currently busy. Please retry the request later. Serwer nie może obecnie przydzielić wystarczającej ilości zasobów, aby spełnić żądanie. Ponów próbę z opóźnieniem. Jeśli błąd będzie się powtarzać, przeprowadź skalowanie w górę bazy danych lub elastycznej puli.
49919 Cannot process create or update request. Too many create or update operations in progress for subscription "%ld". Limit współbieżności na poziomie subskrypcji dla operacji zarządzania. Zmniejszenie równoległych wywołań tworzenia/aktualizacji lub ich rozłożenie.
49920 Cannot process request. Too many operations in progress for subscription "%ld". Limit współbieżności na poziomie subskrypcji dla operacji w locie. Zmniejsz równoległość lub poczekaj, aż trwające operacje się zakończą.

Błędów na poziomie instrukcji nie ma na tej liście, ponieważ występują po nawiązaniu połączenia, a awaria pozostawia sesję w stanie używalnym. Najczęstsze błędy instrukcji, które można ponowić, to 1205 (ofiara impasu) i 1222 (przekroczenie limitu czasu żądania blokady). Ponów całą transakcję zamiast pojedynczej instrukcji, która nie powiodła się.

Tekst komunikatu o błędzie pochodzi z błędów połączenia przejściowego Azure SQL. Poszczególne sterowniki utrzymują własne wbudowane listy ponawiania prób; W tym wykazie opisano, które błędy kwalifikują się do ponawiania próby między SQL Server, Azure SQL Database, Azure SQL Managed Instance, bazą danych SQL w Microsoft Fabric i dedykowanymi pulami SQL w programie Azure Synapse Analytics.

Nie można uzyskać dostępu do serwera (zapora)

Komunikat o błędzie: mssql: login error: Cannot open server '<server>' requested by the login. Client with IP address '203.0.113.42' is not allowed to access the server.

Przyczyny i rozwiązania:

  • Twój adres IP klienta nie znajduje się w regułach zapory Azure SQL. Dodaj regułę zapory w portalu Azure: SQL server>Networking>Dodaj regułę zapory.
  • Jeśli Twoja aplikacja działa w Azure, włącz opcję Zezwalaj usługom i zasobom Azure na dostęp do tego serwera.
  • Aby uzyskać łączność prywatną, skonfiguruj prywatny punkt końcowy.

Osiągnięto limit zasobów

Komunikat o błędzie: mssql: Resource ID: 1. The session limit for the database is 300 and has been reached.

Przyczyny i rozwiązania:

  • Zbyt wiele łączeń równoczesnych dla poziomu Azure SQL. Zmniejsz wartość MaxOpenConns w konfiguracji puli.
  • Przecieki połączeń (niezamknięte wiersze lub transakcje). Sprawdź, czy nie ma zaginionych defer rows.Close() lub defer tx.Rollback() połączeń telefonicznych.
  • Wiele aplikacji współdzielących bazę danych. Podziel limit połączenia między wszystkich klientów.

Aby uzyskać ograniczenia połączeń Azure SQL według tier, zobacz Azure SQL Database.

Usługa jest obecnie przeciążona (ograniczanie przepustowości)

Komunikat o błędzie: mssql: The service is currently busy. Retry the request after 10 seconds. Code: 40501.

Przyczyny i rozwiązania:

  • Baza danych jest pod dużym obciążeniem. Zaimplementuj logikę ponawiania przy użyciu wycofywania wykładniczego.
  • Obciążenie przewyższa pojemność DTU lub vCore danego poziomu. Rozważ skalowanie.

Aby poznać wzorce implementacyjne retry, zobacz Obsługa błędów i wzorce retry.

Baza danych niedostępna obecnie

Komunikat o błędzie: mssql: Database 'AdventureWorks2025' on server '<server>' is not currently available. Code: 40613.

Przyczyna: Azure SQL rekonfiguruje bazę danych (operacja failover, aktualizacja lub skalowanie). Ten warunek jest błędem przejściowym.

Rozwiązanie: Spróbuj operacji ponownie. Baza danych zazwyczaj staje się dostępna w ciągu kilku sekund. Więcej informacji można znaleźć w artykule Obsługa błędów i wzorce ponownych prób.

Błędy połączenia

Błąd driver: bad connection oznacza, że sterownik wykrył, że istniejące połączenie nie jest już użyteczne. Pula database/sql automatycznie ponawia operację na świeżym połączeniu w przypadku wywołań nietransakcyjnych, ale operacje wewnątrz aktywnej transakcji kończą się natychmiast niepowodzeniem.

Nie zaczynaj od tej sekcji, jeśli aplikacja nigdy nie została pomyślnie połączona. driver: bad connection Zazwyczaj oznacza ponowne użycie połączenia, przełączanie awaryjne, przerwę bezczynności lub przerwy w sieci po tym, jak początkowe połączenie już działało.

Typowe przyczyny

Przyczyna Typowy scenariusz Napraw.
Limit czasu bezczynności bramy Azure SQL Połączenie pozostaje bezczynne przez ponad 30 minut za bramą platformy Azure. Ustaw db.SetConnMaxIdleTime(2 * time.Minute) tak, aby poddawał recyklingowi bezczynne połączenia, zanim brama je zamknie.
Przerwy w działaniu sieci Przejściowe awarie sieci między klientem a serwerem. Implementuj logikę powtórek dla operacji nietransakcyjnych. Zobacz Obsługa błędów.
Zakończenie sesji po stronie serwera DBA zakończyło sesję lub serwer został zrestartowany. Ponów próbę. Ustaw opcję db.SetConnMaxLifetime, aby rotować połączenia.
Rekonfiguracja usługi Azure SQL Przełączenie awaryjne, skalowanie lub instalowanie poprawek spowodowały zerwanie połączenia. Ustaw ConnMaxLifetime na 5 minut lub mniej. Zaimplementuj logikę ponawiania prób.
Limit czasu dla długotrwałej transakcji Azure SQL zakończył sesję (błąd 40549). Utrzymuj transakcje krótkie. Podziel duże operacje na mniejsze partie.

Jak baza danych/SQL radzi sobie ze złymi połączeniami

Dla wywołań poza transakcją (db.QueryContext, db.ExecContext), pula database/sql automatycznie ponawia operację przy użyciu nowego połączenia, gdy sterownik zgłasza nieprawidłowe połączenie. To ponowienie próby jest niewidoczne dla twojego kodu.

W przypadku wywołań wewnątrz transakcji (tx.QueryContext, tx.ExecContext) pula nie może ponowić próby, ponieważ stan transakcji zostaje utracony. Twój kod musi wychwycić błąd, cofnąć się i ponownie spróbować całej transakcji.

Konfiguruj pulę tak, aby obsługiwała timeouty i failovery bram Azure:

db.SetConnMaxLifetime(5 * time.Minute)  // Rotate connections to recover from failovers.
db.SetConnMaxIdleTime(2 * time.Minute)  // Recycle before Azure gateway drops idle connections (30 min).
db.SetMaxIdleConns(10)                  // Keep warm connections for quick recovery.
db.SetMaxOpenConns(20)                  // Stay below your tier's connection limit.

W przypadku lokalnego programu SQL Server ConnMaxIdleTime jest mniej istotny, ponieważ nie ma limitu czasu bezczynności bramy. Jednak ustawienie tego zapobiega nietrwałym połączeniom po zakłóceniach sieci.

Szczegółowe wskazówki dotyczące konfiguracji znajdziesz w Azure SQL Database.

Wyczerpanie basenu

Wyczerpanie puli występuje, gdy wszystkie połączenia w puli są zajęte, a nowi dzwoniący blokują się czekając na połączenie.

Symptoms

  • Żądania zwalniają lub wygasają pod obciążeniem.
  • db.Stats().WaitCount rośnie nieustannie.
  • db.Stats().InUse równa się MaxOpenConns.
  • Termin kontekstowy przekraczał błędy podczas szczytowego ruchu.

Diagnoza

Dodaj monitorowanie puli do swojej aplikacji:

stats := db.Stats()
log.Printf("Pool: open=%d inUse=%d idle=%d waitCount=%d waitDuration=%v",
    stats.OpenConnections, stats.InUse, stats.Idle,
    stats.WaitCount, stats.WaitDuration)

Typowe przyczyny i rozwiązania

Przyczyna Jak rozpoznać problem Napraw.
rows.Close() nie wywołano InUse rośnie z czasem, nigdy nie maleje. Dodaj defer rows.Close() po każdym QueryContext.
Długotrwałe transakcje InUse utrzymuje wysoki poziom podczas przetwarzania wsadowego. Utrzymuj transakcje krótkie. Przetwarzaj duże partie w mniejszych częściach.
MaxOpenConns za nisko WaitCount rośnie systematycznie pod normalnym obciążeniem po wykluczeniu przypiętych zasobów i wycieków. Zwiększ wartość MaxOpenConns.
MaxOpenConns nie ustawiono Setki otwartych połączeń przy skokowym obciążeniu. Ustaw MaxOpenConns wartość ograniczoną.
Wyciek goroutine podczas wywoływania db.Conn InUse rośnie bez odpowiadającego temu wzrostu liczby żądań. Upewnij się, że każdy db.Conn() wynik jest zamknięty przez defer conn.Close().

Szczegółowe wskazówki dotyczące konfiguracji puli połączeń można znaleźć w artykule Pula połączeń.

Diagnostyka wolnych lub zablokowanych zapytań

Ustaw limity czasu zapytań

Używaj terminów kontekstowych do wykrywania wolnych zapytań i zapobiegania zablokowanym wywołaniom SQL w wyniku przypinania połączeń i zatrzymywania wywoływaczy:

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

rows, err := db.QueryContext(ctx, "SELECT * FROM LargeTable WHERE Status = @s",
    sql.Named("s", "active"))
if err != nil {
    // Check if the error was a timeout.
    if ctx.Err() == context.DeadlineExceeded {
        log.Println("Query exceeded 5-second timeout")
    }
    return err
}
defer rows.Close()

Pełny opis procesu badania wydajności, obejmującego Query Store, widoki DMV, analizę brakujących indeksów oraz testy porównawcze, można znaleźć w sekcji Dostrajanie wydajności.

Diagnostyka impasu

Komunikat o błędzie: mssql: Transaction (Process ID 52) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

Numer błędu: 1205

Rozwiązanie: Zastoje występują w systemach współbieżnych. Wprowadź automatyczną logikę powtórek dla błędu 1205. Dla funkcji otoczki martwego zablokowania ponownego próbowania, zobacz Transactions.

Strategie zapobiegania:

  • Dostęp do tabel w tej samej kolejności dla wszystkich zapytań.
  • Utrzymuj transakcje krótkie i unikaj interakcji z użytkownikami podczas transakcji.
  • Użyj poziomu izolacji READ COMMITTED SNAPSHOT, aby zmniejszyć rywalizację o blokady.

Powtarzające się blokady na tym samym zapytaniu wskazują na problem projektowy. Użyj grafu zakleszczenia (zarejestrowanego za pomocą Extended Events lub sesji kondycji systemu), aby zidentyfikować kolidujące instrukcje i typy blokad. Pełny poradnik znajdziesz w poradniku Deadlocks. Informacje o strategiach obsługi zakleszczeń w Go można znaleźć w Obsługa zakleszczeń oraz Radzenie sobie z zakleszczeniami.

Błędy certyfikatów przy kontenerach (wersje Go 1.23 i nowsze)

Komunikat o błędzie: x509: negative serial number

Przyczyna: Go 1.23 ściśle egzekwuje RFC 5280. Certyfikat z podpisem własnym generowany przez SQL Server w kontenerach Docker używa ujemnego numeru seryjnego, który Go odrzuca.

Rozwiązania:

  • W środowiskach testowych dodaj TrustServerCertificate=true opcję pominięcia walidacji certyfikatów lub encrypt=disable całkowite wyłączenie szyfrowania.
  • Dla CI/CD ustaw zmienną środowiskową GODEBUG=x509negativeserial=1 tak, aby przywróciła zachowanie sprzed Go 1.23 bez zmiany parametry połączenia.
  • W go.mod (w wersjach Go 1.23 i nowszych) dodaj dyrektywę godebug x509negativeserial=1, aby zastosować przesłonięcie podczas kompilacji.

Uwaga

Nie używaj TrustServerCertificate=true lub encrypt=disable na produkcji. Te opcje wyłączają kontrole bezpieczeństwa. Do produkcji używaj prawidłowo podpisanego certyfikatu.

Błędy certyfikatów SHA-1 (wersje Go 1.24 i nowsze)

Komunikat o błędzie: tls: handshake failure lub TLS Handshake failed: EOF podczas łączenia się ze starszymi instancjami SQL Server.

Przyczyna: Go 1.24 domyślnie zabrania algorytmów podpisu SHA-1 w certyfikatach TLS. Starsze wersje SQL Server oraz niektóre instalacje lokalne wykorzystują certyfikaty podpisane za pomocą SHA-1.

Rozwiązania:

  • Ponownie wydaj certyfikat serwera z SHA-256 lub nowszym (zalecane).
  • Ustaw zmienną środowiskową GODEBUG=tlssha1=1 , aby tymczasowo ponownie włączyć wsparcie SHA-1.
  • W go.mod (wersjach Go 1.23 i nowszych) dodaj dyrektywę godebug tlssha1=1 .

Kiedy używać encrypt=disable, a kiedy TrustServerCertificate=true

Ustawienia Do czego służy Kiedy stosować
TrustServerCertificate=true Szyfruje ruch, ale pomija walidację certyfikatów. Lokalne tworzenie i testowanie, gdzie serwer używa certyfikatu podpisanego samodzielnie.
encrypt=disable Wysyła ruch w formacie jawnym (bez TLS). Środowiska starsze, gdzie TLS nie jest dostępny. Nie polecam.
encrypt=strict TDS 8.0 z pełną walidacją TLS z pierwszego bajtu. Środowisko produkcyjne w SQL Server 2022 lub Azure SQL.

Więcej informacji można znaleźć w sekcji Testowanie i szyfrowanie oraz certyfikaty.

Problemy z kodowaniem i sortowaniem

Ukryte ostrzeżenia o konwersji

Jeśli przekażesz string parametry (wysyłane jako nvarchar) do varchar kolumn, SQL Server wykonuje niejawną konwersję, która może uniemożliwić użycie indeksu.

Ten przykład kontynuuje konfigurację database/sql i mssql z wcześniejszych fragmentów tego artykułu.

Rozwiązanie: Zastosowanie mssql.VarChar dla varchar kolumn:

db.QueryContext(ctx, "SELECT * FROM Production.Product WHERE ProductNumber = @p1",
    mssql.VarChar("FR-R92B-58"))

Błąd CharsetToUTF8 przy znakach niełacińskich

Komunikat o błędzie: CharsetToUTF8: ... podczas zapytania varchar kolumn zawierających znaki chińskie, japońskie lub inne niełacińskie zapisane w zestawieniu takim jak SQL_Latin1_General_CP1_CI_AS.

Przyczyna: Sterownik próbuje przekonwertować stronę kodową kolumny na UTF-8, ale przechowywane bajty nie odpowiadają oczekiwanemu kodowaniu w sortacji.

Rozwiązania:

  • Używaj nvarchar zamiast varchar w przypadku kolumn przechowujących tekst niełaciński. nvarchar przechowuje dane jako UTF-16 i unika konwersji stron kodowych.
  • Jeśli nie możesz zmienić typu kolumny, sprawdź, czy sortowanie bazy danych obsługuje zestaw znaków, który przechowujesz.

Włącz rejestrowanie diagnostyczne

Użyj parametru połączenia log , aby umożliwić logowanie na poziomie sterownika:

sqlserver://<user>:<password>@<server>?database=AdventureWorks2025&log=63

Flagi dziennika to wartości maski bitowej: 1 (błędy), 2 (komunikaty), 4 (wiersze), 8 (SQL), 16 (parametry), 32 (transakcje), 64 (debugowanie). Łącz wartości, dodając je (na przykład 63 = wszystkie oprócz debugowania, 127 = wszystkie).

Do programowego logowania użyj SetLogger lub SetContextLogger. Zobacz Rejestrowanie i diagnostyka.

Lista kontrolna rozwiązywania problemów

Objaw Pierwszy krok
Odmowa połączenia Sprawdź, czy SQL Server działa i że TCP/IP jest włączone.
Logowanie nie powiodło się Sprawdź dane uwierzytelniające i tryb uwierzytelniania.
Błąd certyfikatu Sprawdź certyfikat serwera lub ustaw TrustServerCertificate=true (tylko w środowisku deweloperskim).
Przekroczenie limitu czasu połączenia Weryfikuj ścieżkę sieciową za pomocą Test-NetConnection. Sprawdzanie reguł zapory.
Zapora Usługi Azure SQL Dodaj swój adres IP do reguł zapory Azure SQL.
Błędy ograniczania przepustowości Wdróż mechanizm ponawiania prób z wykładniczym wydłużaniem odstępów. Przejdź na wyższy poziom.
Złe połączenie Ustaw ConnMaxIdleTime poniżej 30 minut dla Azure SQL. Zaimplementuj logikę ponawiania prób.
Wyczerpanie basenu Monitor db.Stats(). Napraw niezamknięte wiersze/transakcje. Zwiększ wartość MaxOpenConns.
Wolne zapytania Ustaw limity czasu kontekstu. Pytaj DMV o drogie zapytania.
Deadlocks Wprowadź powtórkę przy błędzie 1205. Dostęp do tabel w spójnej kolejności.
Niejawna konwersja Użyj mssql.VarChar w przypadku kolumn varchar.