【问题标题】:Cannot connect to SQL Server database using pymssql but can connect using underlying freetds tsql无法使用 pymssql 连接到 SQL Server 数据库,但可以使用底层 freetds tsql 连接
【发布时间】:2012-04-24 15:49:49
【问题描述】:

我不知道为什么会收到此错误并且找不到任何解决方案。我可以使用 freetds tsql 连接到 SQL Server 数据库,但是在使用 pymssql.connect 连接时不断出现错误。

具体错误是:

pymssql.OperationalError:(18456,“用户 'xxx' 登录失败。DB-Lib 错误消息 18456,严重性 14:\n常规 SQL Server 错误:检查来自 SQL Server 的消息\nDB-Lib 错误消息 20002, 严重性 9:\n自适应服务器连接失败\n")

我将 freetds 的配置设置为:

[custom_config]
    host = myhost
    port = 1433
    tds version = 7.0
    encryption = request
    dump file = /tmp/freetds.log

运行:

tsql -S custom_config -U tsmv -P xxx

返回:

locale is "en_US.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"
1>

这让我可以查询数据库。

但是,运行:

python
>> import pymssql
>> pymssql.connect(server='custom_config', user='user', password='xxx',    database='database')

引发上述错误。

我正在使用 Linux CentOS,python 2.6.6,freetds 0.92 dev(我尝试过使用 tdsver=7.0 编译的其他版本)。

freetds 日志是:

log.c:196:Starting log file for FreeTDS 0.92
on 2012-04-12 10:39:15 with debug flags 0x4fff.
iconv.c:330:tds_iconv_open(0x1391b70, ISO-8859-1)
iconv.c:187:local name for ISO-8859-1 is ISO-8859-1
iconv.c:187:local name for UTF-8 is UTF-8
iconv.c:187:local name for UCS-2LE is UCS-2LE
iconv.c:187:local name for UCS-2BE is UCS-2BE
iconv.c:349:setting up conversions for client charset "ISO-8859-1"
iconv.c:351:preparing iconv for "ISO-8859-1" <-> "UCS-2LE" conversion
iconv.c:391:preparing iconv for "ISO-8859-1" <-> "UCS-2LE" conversion
iconv.c:394:tds_iconv_open: done
net.c:205:Connecting to xx.x.x.xxx port 1433 (TDS version 7.1)
net.c:270:tds_open_socket: connect(2) returned "Operation now in progress"
net.c:310:tds_open_socket() succeeded
util.c:156:Changed query state from DEAD to IDLE
net.c:741:Sending packet
0000 12 01 00 34 00 00 00 00-00 00 15 00 06 01 00 1b |...4.... ........|
0010 00 01 02 00 1c 00 0c 03-00 28 00 04 ff 08 00 01 |........ .(......|
0020 55 00 00 02 4d 53 53 51-4c 53 65 72 76 65 72 00 |U...MSSQ LServer.|
0030 c7 39 00 00            -                        |.9..|

net.c:555:Received header
0000 04 01 00 25 00 00 01 00-                        |...%....|

net.c:609:Received packet
0000 04 01 00 25 00 00 01 00-00 00 15 00 06 01 00 1b |...%.... ........|
0010 00 01 02 00 1c 00 01 03-00 1d 00 00 ff 0a 00 0f |........ ........|
0020 a0 00 00 02 00         -                        |.....|

login.c:1057:detected flag 2
login.c:782:quietly sending TDS 7+ login packet
token.c:328:tds_process_login_tokens()
net.c:555:Received header
0000 04 01 00 72 00 51 01 00-                        |...r.Q..|

net.c:609:Received packet
0000 04 01 00 72 00 51 01 00-aa 5e 00 18 48 00 00 01 |...r.Q.. .^..H...|
0010 0e 1d 00 4c 00 6f 00 67-00 69 00 6e 00 20 00 66 |...L.o.g .i.n. .f|
0020 00 61 00 69 00 6c 00 65-00 64 00 20 00 66 00 6f |.a.i.l.e .d. .f.o|
0030 00 72 00 20 00 75 00 73-00 65 00 72 00 20 00 27 |.r. .u.s .e.r. .'|
0040 00 74 00 73 00 6d 00 76-00 27 00 2e 00 0c 4d 00 |.t.s.m.v .'....M.|
0050 43 00 53 00 2d 00 44 00-41 00 54 00 41 00 42 00 |C.S.-.D. A.T.A.B.|
0060 41 00 53 00 45 00 00 01-00 fd 02 00 00 00 00 00 |A.S.E... ........|
0070 00 00                  -                        |..|

token.c:337:looking for login token, got  aa(ERROR)
token.c:122:tds_process_default_tokens() marker is aa(ERROR)
token.c:2588:tds_process_msg() reading message 18456 from server
token.c:2661:tds_process_msg() calling client msg handler
dbutil.c:85:_dblib_handle_info_message(0x14e2e30, 0x1391b70, 0x7fff8b047e40)
dbutil.c:86:msgno 18456: "Login failed for user 'xxx'."
token.c:2674:tds_process_msg() returning TDS_SUCCEED
token.c:337:looking for login token, got  fd(DONE)
token.c:122:tds_process_default_tokens() marker is fd(DONE)
token.c:2339:tds_process_end: more_results = 0
    was_cancelled = 0
    error = 1
    done_count_valid = 0
token.c:2355:tds_process_end() state set to TDS_IDLE
token.c:2370:                rows_affected = 0
token.c:438:tds_process_login_tokens() returning TDS_FAIL
login.c:466:login packet accepted
util.c:156:Changed query state from IDLE to DEAD
util.c:331:tdserror(0x14e2e30, 0x1391b70, 20002, 0)
dblib.c:7929:dbperror(0x1383c70, 20002, 0)
dblib.c:7981:20002: "Adaptive Server connection failed"
dblib.c:8002:"Adaptive Server connection failed", client returns 2 (INT_CANCEL)
util.c:361:tdserror: client library returned TDS_INT_CANCEL(2)
util.c:384:tdserror: returning TDS_INT_CANCEL(2)
dblib.c:1443:dbclose(0x1383c70)
dblib.c:258:dblib_del_connection(0x7fa462faf540, 0x1391b70)
mem.c:615:tds_free_all_results()
dblib.c:305:dblib_release_tds_ctx(1)
dblib.c:5882:dbfreebuf(0x1383c70)
dblib.c:739:dbloginfree(0x1533a40)

我完全不知道为什么这不起作用。任何帮助将非常感激。

【问题讨论】:

  • 您可能希望使用 servername 而不是 server。此外,我遇到了问题(至少对于 pyodbc),连接字符串的行为似乎与传递 kwargs 的行为不完全相同(尽管可能是我的错误......)。您也可以尝试使用 pyodbc 而不是 pymssql(这里没有使用 pymssql 的经验)。
  • 谢谢 Derek,我接受了你的建议,放弃了使用 pymssql 并开始使用带有 Microsoft 的 Linux 驱动程序的 pyodbc。现在一切正常(尽管我知道这不能回答我原来的问题)。

标签: sql-server tsql freetds pymssql


【解决方案1】:

“自适应服务器连接失败”似乎是一个相当笼统的消息,但这里有一些事情可以尝试。

  1. 此邮件列表线程 (http://lists.ibiblio.org/pipermail/freetds/2010q3/026060.html) 表示使用不正确的 TDS 协议会导致“自适应服务器连接失败”消息。在chewynougat 的日志中似乎并非如此,但也许它对其他人有所帮助。

  2. 此常见问题解答提供了许多尝试步骤: https://github.com/pymssql/pymssql/blob/87f4383ec153962b7ca7e63a05042d3f09005178/docs/faq.rst,

一个正在尝试通过 tsql -H 测试 tds 连接,它绕过从 conf 读取并仅读取传入的值。鉴于上面的 conf 包含端口和协议版本,可能值得与 tsql -C 一起检查以查看是否需要调整。

  1. 此外,在常见问题解答的底部,它指出

    真正的“登录错误”消息的代码=18456 和严重性=14

那是正在发送的错误消息,因此也许可以尝试登录审核 (http://msdn.microsoft.com/en-us/library/ms175850.aspx) 以查看 pymssql 是否正确传递了您的凭据。
  1. 同一部分讨论了混淆 mssql.connect 的不同字符集,因此也可以尝试使用基本密码(即 ASCII 65-90)以确保在翻译过程中不会丢失任何内容。看起来 Aki 和日语一起工作,所以也许这也是一个原因。

【讨论】:

    【解决方案2】:

    我遇到了同样的问题。幸运的是,我发现了问题所在。我的机器上有两个不同版本的 FreeTDS。我安装了其中一个(v 0.91):

       sudo apt-get install freetds-dev
    

    后来我发现它不是最后一个版本,我从 freetds.org 下载了 Freetds 的 tar 文件。当我运行 tsql -C.它显示了正确的路径,我正确地操纵了 freetds.conf。通过更改环境变量(http://www.freetds.org/userguide/envvar.htm),我可以连接到数据库。但是,每次我尝试通过 Pymssql 连接时都会出错。

    最后,我查看了日志文件,发现 Python 使用的是旧版本(v 0.91),但我的最后一个版本是 0.95。

    >>> import os
    >>> os.environ['TDSDUMP'] = 'stdout'
    >>>
    >>> import pymssql
    >>> conn = pymssql.connect(server="sqlserverhost")
    

    所以,我删除了 0.91 版本:

    sudo apt-get purge freetds-common
    

    并且 pymssql 连接到具有正确配置的正确版本。

    它也可以帮助你。

    【讨论】:

      【解决方案3】:

      尝试遵循 pymssql 文档中的新注释:azure 需要照顾用户部分。这太奇怪了,但有效。 ms sql 仓库让在 linux/mac 上的工作变得如此困难..

      http://pymssql.org/en/latest/azure.html

      重要提示:请勿将 username@server.database.windows.net 用于相关 connect() 调用的用户参数!您必须改用较短的 username@server 表单!

      【讨论】:

        【解决方案4】:

        我在通过pip install pymssql 安装时遇到了同样的问题,因为它安装了一个预构建的不支持加密的特定于操作系统的二进制轮。

        尽管我已经安装了特定版本的 freetds,但我预计会使用它。使用pip install --no-binary pymssql pymssql 代替安装可以正常安装。

        如果您想加密您的数据库连接,您需要首先构建/安装 freetds,然后按照此处所述安装 pymssql。

        在这种情况下,我强烈建议确保您的 freetds.conf 文件指定“require”而不是“request”,以避免默默地退回到未加密的流量。对 SQL 关键字使用tcpdump -A 和 grepping 可以帮助确定流量是否真正加密。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-02-09
          • 2016-07-16
          • 1970-01-01
          • 2018-04-23
          • 2011-05-08
          • 2020-02-11
          • 2016-03-20
          相关资源
          最近更新 更多