Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Драйверът Go with SQL Server не може да се свърже успешно, неуспешно влизане

Искам да споделя опита си в разработването на проста демонстрационна програма за база данни на език Go с помощта на SQL Server Express 2008. Вярвам, че следните научени уроци ще се прилагат за всяка версия на SQL Server от 2008 г. и по-късно.

Моят SQL Server Express беше инсталиран преди това с default екземпляр, а не named екземпляр. Също така беше инсталиран за използване на удостоверяване на Windows. И двете от тези настройки се изискваха от друга разработка, която върша. Другата работа, която върша, използва SQL Server Express на същия компютър като приложението като локална база данни. Очаквах да мога да използвам удостоверяване на Windows със SQL Server в моето приложение Go.

Търсейки драйвер и малка примерна програма за използване с локален SQL Server и Go, този въпрос се появи при търсенето ми. Реших да добавя малко допълнителна информация и примерна програма, за да помогна на другите да започнат и да се поучат от грешките ми. Също така намерих тази статия GoLang и MSSQL бази данни:пример за полезен, особено след като направих достатъчно грешки, за да го разбера по-добре.

Окончателната версия на моята тестова програма е следната:

package main

import (
    "fmt"
    "log"
    "database/sql"
     _ "github.com/denisenkom/go-mssqldb"     // the underscore indicates the package is used
)    

func main() {
    fmt.Println("starting app")

    // the user needs to be setup in SQL Server as an SQL Server user.
    // see create login and the create user SQL commands as well as the
    // SQL Server Management Studio documentation to turn on Hybrid Authentication
    // which allows both Windows Authentication and SQL Server Authentication.
    // also need to grant to the user the proper access permissions.
    // also need to enable TCP protocol in SQL Server Configuration Manager.
    //
    // you could also use Windows Authentication if you specify the fully qualified
    // user id which would specify the domain as well as the user id.
    // for instance you could specify "user id=domain\\user;password=userpw;".

    condb, errdb := sql.Open("mssql", "server=localhost;user id=gouser;password=g0us3r;")
    if errdb  != nil {
        fmt.Println("  Error open db:", errdb.Error())
    }

    defer condb.Close()

    errdb = condb.Ping()
    if errdb != nil {
        log.Fatal(errdb)
    }

    // drop the database if it is there so we can recreate it
    // next we will recreate the database, put a table into it,
    // and add a few rows.
    _, errdb = condb.Exec("drop database mydbthing")
    if errdb != nil {
        fmt.Println("  Error Exec db: drop db - ", errdb.Error())
    }

    _, errdb = condb.Exec("create database mydbthing")
    if errdb  != nil {
        fmt.Println("  Error Exec db: create db - ", errdb.Error())
    }

    _, errdb = condb.Exec("use  mydbthing")
    if errdb  != nil {
        fmt.Println("  Error Exec db: using db - ", errdb.Error())
    }

    _, errdb = condb.Exec("create table junky (one int, two int)")
    if errdb  != nil {
        fmt.Println("  Error Exec db: create table - ", errdb.Error())
    }

    _, errdb = condb.Exec("insert into junky (one, two) values (101, 201)")
    if errdb  != nil {
        fmt.Println("  Error Exec db: insert table 1 - ", errdb.Error())
    }
    _, errdb = condb.Exec("insert into junky (one, two) values (102, 202)")
    if errdb  != nil {
        fmt.Println("  Error Exec db: insert table 2 - ", errdb.Error())
    }
    _, errdb = condb.Exec("insert into junky (one, two) values (103, 203)")
    if errdb  != nil {
        fmt.Println("  Error Exec db: insert table 3 - ", errdb.Error())
    }

    // Now that we have our database lets read some records and print them.
    var (
        one  int
        two  int
    )

    // documentation about a simple query and results loop is at URL
    // http://go-database-sql.org/retrieving.html
    // we use Query() and not Exec() as we expect zero or more rows to
    // be returned. only use Query() if rows may be returned.
    fmt.Println ("  Query our table for the three rows we inserted.")
    rows, errdb := condb.Query ("select one, two from junky")
    defer rows.Close()
    for rows.Next() {
        err:= rows.Scan (&one, &two)
        if err != nil {
            fmt.Println("  Error Query db: select - ", err.Error())
        } else {
            fmt.Printf("    - one %d and two %d\n", one, two)
        }
    }
    rows.Close()

    errdb = rows.Err()
    if errdb != nil {
        fmt.Println("  Error Query db: processing rows - ", errdb.Error())
    }

    fmt.Println("ending app")
}

Първият път, когато горното приложение се стартира, след като бъдат направени необходимите промени в настройките на SQL Server, то ще генерира следния изход. Тъй като базата данни не съществува при първото стартиране на програмата, ще видите отпечатано съобщението за грешка. Въпреки това при последващи стартиране базата данни ще съществува и съобщението за грешка, когато базата данни бъде отпаднала съществува, няма да бъде изведена.

starting app
  Error Exec db: drop db -  mssql: Cannot drop the database 'mydbthing', because it does not exist or you do not have permission.
  Query our table for the three rows we inserted.
    - one 101 and two 201
    - one 102 and two 202
    - one 103 and two 203
ending app

Инсталиране на пакета драйвери за SQL Server

Първото нещо, което трябваше да направя, беше да намеря пакет с драйвер за база данни, който да работи със SQL Server. Препоръчани няколко публикации в stackoverflow github.com/denisenkom/go-mssqldb така че това е, което се използва.

За да използвате github.com/denisenkom/go-mssqldb пакет Първо трябваше да го извлека от хранилището на github, използвайки go get github.com/denisenkom/go-mssqldb от прозореца на командната обвивка, създаден чрез стартиране на Git Shell .

Git Shell е обвивката на github, която се инсталира като част от инсталирането на Git. Открих, че трябва да стартирам go get команда в Git Shell за go команда, за да намерите git приложение и достъп до хранилището на github. Когато се опитах да стартирам go get команда от нормална командна обвивка Видях съобщение за грешка, което показва, че git командата не може да бъде намерена.

След инсталиране на go-mssqldb пакет. Успях да стартирам моето примерно приложение и продължих да срещам грешка по време на изпълнение от Open() . Резултатът от моето приложение беше следният:

starting app

Error Exec db: create db -  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.

ending app

Разрешаване на TCP връзки за SQL Server

След известно търсене намерих редица различни сайтове, които всички показват, че грешката означава, че моят екземпляр на SQL Server не е конфигуриран за TCP/IP. Различните публикации показват, че трябва да използвам Sql Server Configuration Manager за да активирате TCP/IP.

Това, което открих, е, че всъщност има две места, където TCP/IP трябва да бъде активиран. Единият беше Client Protocols и това наистина вече беше активирано. Другото обаче беше Protocols for MSSQLSERVER и в този TCP/IP беше деактивиран. Така че активирах TCP/IP в Protocols for MSSQLSERVER раздел, след което рестартира услугата SQL Server с помощта на помощната програма за обслужване на Административните инструменти от контролния панел.

Въпреки това все още имах проблеми с всякакъв вид заявка, след като използвах sql.Open() . Виждах изход на приложението, който беше някаква вариация на следното. Съобщението за грешка беше същото, но когато извикванията на функции са имали грешки, може да се променят от едно изпълнение към следващо. Опитах се да променя низа за връзка, посочен в sql.Open() без резултати, освен различни съобщения за грешки.

starting app
  Error Exec db: create db -  driver: bad connection
  Error Exec db: create table -  driver: bad connection
ending app

Ровейки се по-нататък, намерих тази бележка в хранилището на github:

Известни проблеми

Двигателят на SQL Server 2008 и 2008 R2 не може да обработва записи за влизане, когато SSL криптирането не е деактивирано. За да коригирате проблем със SQL Server 2008 R2, инсталирайте SQL Server 2008 R2 Service Pack 2. За да коригирате проблема с SQL Server 2008, инсталирайте Microsoft SQL Server 2008 Service Pack 3 и Cumulativeupdate package 3 за SQL Server 2008 SP3. Повече информация:http://support.microsoft.com/kb/2653857

Така че изтеглих актуализациите, които всъщност никога не съм инсталирал. Докато чаках изтеглянето, разгледах още и намерих папката, съдържаща действителния изпълним файл на SQL Server заедно с Log папка, съдържаща поредица от файлове ERRORLOG , ERRORLOG.1 и др.

Регистрите на SQL Server показват, че е необходим потребител на SQL Server

Търсене в ERRORLOG файл Намерих регистър за грешки на SQL Server със следните регистрационни файлове, които предоставиха следващото парче от пъзела:

2016-08-15 22:56:22.41 Server      SQL Server is now ready for client connections. This is an informational message; no user action is required.
2016-08-15 23:55:47.51 Logon       Error: 18456, Severity: 14, State: 58.
2016-08-15 23:55:47.51 Logon       Login failed for user 'rchamber'. Reason: An attempt to login using SQL authentication failed. Server is configured for Windows authentication only. [CLIENT: 127.0.0.1]
2016-08-15 23:55:47.61 Logon       Error: 18456, Severity: 14, State: 58.
2016-08-15 23:55:47.61 Logon       Login failed for user 'rchamber'. Reason: An attempt to login using SQL authentication failed. Server is configured for Windows authentication only. [CLIENT: ::1]
2016-08-15 23:55:47.62 Logon       Error: 18456, Severity: 14, State: 58.
2016-08-15 23:55:47.62 Logon       Login failed for user 'rchamber'. Reason: An attempt to login using SQL authentication failed. Server is configured for Windows authentication only. [CLIENT: 127.0.0.1]

Тогава разбрах, че драйверът на Go SQL Server не използва удостоверяване на Windows, а вместо това използва удостоверяване на SQL Server. Бях се опитал да използвам удостоверяване на Windows, като посочих празен user id= обаче това изглежда не проработи. Така че с помощта на sqlcmd помощна програма, създадох потребител на SQL Server.

1> create login gouser with password='g0us3r';
2> go
1> create user gouser for login gouser;
2> go

След това изтеглих и инсталирах Microsoft SQL Server Management Studio. Това е различна помощна програма от SQL Server Configuration Manager. Използвайки това, направих две неща:(1) включих удостоверяването на SQL Server, както и удостоверяването на Windows и (2) предоставих необходимите разрешения за моя нов потребител на SQL Server gouser . Тази помощна програма също така предоставя приятен потребителски интерфейс за разглеждане на SQL Server и различните му бази данни.

Уверете се, че потребителят на SQL, който създавате, има достатъчно разрешения, за да може да се използва за свързване към SQL Server и създаване на база данни.

Някои съображения за използване на удостоверяване на Windows

След допълнително проучване установих, че всъщност мога да използвам удостоверяване на Windows, но трябва да бъдат предоставени напълно квалифицираният потребителски идентификатор и неговата парола. За среда, използваща Active Directory с име на домейн "AD", напълно квалифицираният потребителски идентификатор ще бъде "AD\userid", а за локалния хост ще бъде "\userid". Все още проучвам как мога да използвам автоматично идентификационните данни на влезлия в момента потребител.

След още по-нататъшни проучвания и намиране на помощ от разработчиците на драйвери Go, удостоверяването на Windows с текущата би трябвало да е възможно, ако sql.Open() не включва информацията за потребителя, означаваща "потребителски идентификатор=;парола=;" не трябва да се посочва.

Тази форма на автоматично удостоверяване на Windows срещу текущия потребител обаче е разрешена само ако екземплярът на SQL Server използва Kerberos с валидно име на главния служител (SPN). Ако извършите рестартиране на вашия екземпляр на SQL Server и видите следния регистър във вашия ERRORLOG файл, SQL Server не можа да се инициализира с Kerberos.

2016-08-23 18:32:16.77 Сървър Библиотеката на мрежовия интерфейс на SQL Server не можа да регистрира името на принципа на услугата (SPN) за услугата SQL Server. Грешка:0x54b, състояние:3. Неуспехът при регистриране на SPN може да доведе до връщане на интегрираната автентификация към NTLM вместо Kerberos. Това е информационно съобщение. Допълнителни действия се изискват само ако удостоверяването на Kerberos се изисква от правилата за удостоверяване.

Вижте също Как да се уверите, че използвате удостоверяване на Kerberos, когато създавате отдалечена връзка към екземпляр на SQL Server 2005, който предоставя допълнителна информация, както и с помощта на setspn команда за коригиране на проблема.

Вижте също Библиотеката на SQL мрежов интерфейс не успя да регистрира SPN.

Относно довереното удостоверяване на Windows (Актуализирано според заявка от @Richard от @xpt)

Удостоверяването на Windows е влизане в SQL Server с идентификационни данни на Windows, без да се посочва потребителски идентификатор и парола. Това се нарича доверена връзка за sqlcmd или ODBC; или се нарича Single-Sign-On за go-mssqldb Отидете на пакет с драйвери.

От go-mssqldb е readme в github,

"user id" - въведете потребителския идентификатор на SQL Server или потребителския идентификатор на WindowsAuthentication във формат DOMAIN\User. В Windows, ако потребителският идентификатор е празен или липсва единичен вход, се използва.

Така че опитах следните два начина с моя SQL Server 2008 R2 и и двата просто работят добре:

condb, errdb := sql.Open("mssql", "server=MyServer;user id=;password=DONTCARE;")
condb, errdb := sql.Open("mssql", "server=MyServer;user id=;password=;")

Имайте предвид, че използването на server=localhost би се провалило, тъй като е важно да имате правилното име на хост, от това име драйверът изгражда основното име на услугата kerberos (SPN) на SQL Server и това име трябва да съвпада с това на SQL Server. Използвах правилно име на главния служител (SPN) с моя тест, така че работи.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Използване на колона за сортиране в таблица на база данни

  2. Проверете за неуспешен имейл в SQL Server (T-SQL)

  3. Как да конвертирате Unix Timestamp в стойност на дата/час в SQL Server

  4. Размито съвпадение с помощта на T-SQL

  5. Как мога да изтрия дублиращи се редове в таблица