Python 使用 pymssql 连接 SQL Server 报错:DB-Lib error message 20002, severity 9
作者:mmseoamin日期:2024-04-01

文章目录

  • 版本说明
  • 排查过程
  • 参考
  • 个人简介

    版本说明

    • Python 3.8
    • SQL Server 2008
    • pymssql 2.2.11

      排查过程

      • 最近给一个学妹看一个 Python 使用 pymssql 连接 SQL Server 报错问题,具体报错信息如下:
        Error: (20002, b'DB-Lib error message 20002, severity 9:\nAdaptive Server connection failed (127.0.0.1)\nDB-Lib error message 20002,
        severity 9:\nAdaptive Server connection failed (127.0.0.1)\n')
        
        • 学妹本地使用 SQL Server 客户端是可以连接上的,但是使用代码就是连接不上,为了方便测试,我先写一个简单的测试代码:
          import pymssql
          # 尝试连接数据库
          try:
              # 建立连接
              connection = pymssql.connect('127.0.0.1','xjy_0513', '12345678', '学生住宿服务系统')
              # 获取游标
              cursor = connection.cursor()
              # 执行 SQL 查询或操作
              # 提交事务(如果有更改)
              connection.commit()
          except pymssql.Error as e:
              print(f"Error: {e}")
          finally:
              # 关闭连接
              if connection:
                  connection.close()
          
          • 考虑到目前的可能性,大致怀疑是学妹电脑网络配置的问题,然后一顿搜索这个问题,网络、字符集都尝试了还是无法解决问题,最终在一个角落看到一个可以打印详细连接过程的方式:
            import pymssql
            import os
            os.environ['TDSDUMP'] = 'stdout' # 用于打印连接详细过程
            # 尝试连接数据库
            try:
                # 建立连接
                connection = pymssql.connect('127.0.0.1','xjy_0513', '12345678', '学生住宿服务系统')
                # 获取游标
                cursor = connection.cursor()
                # 执行 SQL 查询或操作
                # 提交事务(如果有更改)
                connection.commit()
            except pymssql.Error as e:
                print(f"Error: {e}")
            finally:
                # 关闭连接
                if connection:
                    connection.close()
            
            • 阅读整个连接详细日志,我发现了一些关键信息,以下是截取的部分:
              log.c:187:Starting log file for FreeTDS 1.4.9
                      on 2023-12-26 22:12:39 with debug flags 0x4fff.
              dblib.c:1187:tdsdbopen(00000235D7C34090, 127.0.0.1:1433, [microsoft])
              dblib.c:1213:tdsdbopen: dbproc->dbopts = 00000235D7B91F60
              dblib.c:1224:tdsdbopen: tds_set_server(00000235D7BAAF60, "127.0.0.1:1433")
              dblib.c:251:dblib_get_tds_ctx(void)
              dblib.c:1241:tdsdbopen: About to call tds_read_config_info...
              config.c:170:Getting connection information for [127.0.0.1:1433].
              // 貌似一个配置文件找不到 但是网上好像都没有提到过这个配置文件
              config.c:174:Attempting to read conf files.
              config.c:362:... $FREETDSCONF not set.  Trying $FREETDS/etc.
              config.c:375:... $FREETDS not set.  Trying $HOME.
              config.c:301:Could not open 'C:\Users\lenovo\AppData\Roaming/.freetds.conf' ((.freetds.conf)).
              config.c:301:Could not open 'c:\freetds.conf' ((default)).
              config.c:362:... $FREETDSCONF not set.  Trying $FREETDS/etc.
              config.c:375:... $FREETDS not set.  Trying $HOME.
              config.c:301:Could not open 'C:\Users\lenovo\AppData\Roaming/.freetds.conf' ((.freetds.conf)).
              config.c:301:Could not open 'c:\freetds.conf' ((default)).
              config.c:839:Setting 'dump_file' to 'stdout' from $TDSDUMP.
              config.c:725:tds_config_login: client_charset is UTF-8.
              config.c:734:tds_config_login: database_name is 瀛︾敓浣忓鏈嶅姟绯荤粺.
              config.c:839:Setting 'dump_file' to 'stdout' from $TDSDUMP.
              dblib.c:1268:tdsdbopen: Calling tds_connect_and_login(00000235D7BF2D20, 00000235D9B6AEA0)
              iconv.c:371:tds_iconv_open(00000235D9B3C450, UTF-8, 1)
              iconv.c:356:Using trivial iconv
              iconv.c:202:local name for ISO-8859-1 is ISO-8859-1
              iconv.c:202:local name for UTF-8 is UTF-8
              iconv.c:202:local name for UCS-2LE is UCS-2LE
              iconv.c:202:local name for UCS-2BE is UCS-2BE
              iconv.c:390:setting up conversions for client charset "UTF-8"
              iconv.c:392:preparing iconv for "UTF-8" <-> "UCS-2LE" conversion
              iconv.c:431:tds_iconv_open: done
              net.c:391:Connecting with protocol version 7.4
              net.c:318:Connecting to 127.0.0.1 port 1433
              "et.c:340:tds_setup_socket: connect(2) returned "无法立即完成一个非阻止性套接字操作。
              .....省略
              dblib.c:6088:dbfreebuf(00000235D7B91B90)
              dblib.c:739:dbloginfree(00000235D7C34090)
              Error: (20002, b'DB-Lib error message 20002, severity 9:\nAdaptive Server connection failed (127.0.0.1)\nDB-Lib error message 20002, severity 9:\nAdaptive Server connection failed (127.0.0.1)\n')
              Traceback (most recent call last):
              
              • 阅读 pymssql 开发文档发现,pymssql uses FreeTDS package to connect to SQL Server instances ,因此需要配置 FreeTDS:
              • 完整说明:pymssql uses FreeTDS package to connect to SQL Server instances. You have to tell it how to find your database servers. The most basic info is host name, port number, and protocol version to use.The system-wide FreeTDS configuration file is /etc/freetds.conf or C:\freetds.conf, depending upon your system. It is also possible to use a user specific configuration file, which is $HOME/.freetds.conf on Linux and %APPDATA%\.freetds.conf on Windows. Suggested contents to start with is at least:
                [global]
                    port = 1433
                    tds version = 7.0
                
                • 在对应路径上添加 FreeTDS 配置文件,运行成功,再次观察运行日志正确查找到了配置文件。
                  log.c:187:Starting log file for FreeTDS 1.4.9
                          on 2023-12-26 22:14:14 with debug flags 0x4fff.
                  dblib.c:1187:tdsdbopen(000002CC6963F000, 127.0.0.1:1433, [microsoft])
                  dblib.c:1213:tdsdbopen: dbproc->dbopts = 000002CC6B626980
                  dblib.c:1224:tdsdbopen: tds_set_server(000002CC695BBB30, "127.0.0.1:1433")
                  dblib.c:251:dblib_get_tds_ctx(void)
                  dblib.c:1241:tdsdbopen: About to call tds_read_config_info...
                  config.c:170:Getting connection information for [127.0.0.1:1433].
                  config.c:174:Attempting to read conf files.
                  config.c:362:... $FREETDSCONF not set.  Trying $FREETDS/etc.
                  config.c:375:... $FREETDS not set.  Trying $HOME.
                  config.c:301:Could not open 'C:\Users\lenovo\AppData\Roaming/.freetds.conf' ((.freetds.conf)).
                  config.c:305:Found conf file 'c:\freetds.conf' (default).
                  config.c:513:Looking for section global.
                  config.c:572:   Found section global.
                  config.c:575:Got a match.
                  config.c:598:   port = '1433'
                  config.c:598:   tds version = '7.0'
                  config.c:957:Setting tds version to 7.0 (0x700).
                  ....省略
                  dblib.c:236:dblib_del_connection(00007FFD05304C90, 000002CC69658880)
                  query.c:3804:tds_disconnect()
                  util.c:179:Changed query state from IDLE to DEAD
                  mem.c:665:tds_free_all_results()
                  dblib.c:278:dblib_release_tds_ctx(1)
                  dblib.c:6088:dbfreebuf(000002CC6B6265B0)
                  

                  参考

                  • https://www.pymssql.org/en/v2.1.2/freetds.html#configuration

                    个人简介

                    👋 你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.

                    🚀 我对技术的热情是我不断学习和分享的动力。我的博客是一个关于Java生态系统、后端开发和最新技术趋势的地方。

                    🧠 作为一个 Java 后端技术爱好者,我不仅热衷于探索语言的新特性和技术的深度,还热衷于分享我的见解和最佳实践。我相信知识的分享和社区合作可以帮助我们共同成长。

                    💡 在我的博客上,你将找到关于Java核心概念、JVM 底层技术、常用框架如Spring和Mybatis 、MySQL等数据库管理、RabbitMQ、Rocketmq等消息中间件、性能优化等内容的深入文章。我也将分享一些编程技巧和解决问题的方法,以帮助你更好地掌握Java编程。

                    🌐 我鼓励互动和建立社区,因此请留下你的问题、建议或主题请求,让我知道你感兴趣的内容。此外,我将分享最新的互联网和技术资讯,以确保你与技术世界的最新发展保持联系。我期待与你一起在技术之路上前进,一起探讨技术世界的无限可能性。

                    📖 保持关注我的博客,让我们共同追求技术卓越。