admin

  • 实测Aurora Serverless v2

    ·

    Aurora自2014年发布以来,一直是AWS的最核心数据库产品,而Serverless则是这个产品最重要的功能之一了。在2018年08月,Serverless功能刚刚GA,当时做过一次测试(参考)。在2020年底的re:Invent上,Andy Jassy宣布Aurora发布Serverless v2,时隔一年半,终于GA,一起来看看实际效果怎样吧。

    在最近看到该功能的介绍文章中,使用了”几分之一秒内扩展”、” scales instantly and nondisruptively “等描述,对此,我是保持怀疑的,这也要实测一下的原因,从一个用户感受的角度,看看一次升级(scaling)需要多长时间。

    测试结果概述

    • 在这次实际测试中,新的Serverless v2,可以将scaling up的时间降低到10秒级别。系统压力上来后,首次升级(scaling up)花了13秒,之后的几次升级分别花了7秒、4秒、10秒等。在这几秒内,Aurora需要完成监控采集、分析与决策,变配动作完成等动作。于用户侧,系统压力突增时,10秒内Aurora就会完成升级,这是非常实用和强大的。
    • 相比4年前GA版本数分钟级别的升级(scaling),新的版本提升非常大。不过,与宣传的亚秒级( in a fraction of a second )还有差距的。当然,一种猜测是,”亚秒内”完成的是变配动作本身,不包括监控、决策与命令下发等过程。
    • Scaling down是逐步阶梯式完成的,每次间隔约1分钟,这是符合预期的。
    • 新的版本与旧版本有非常好的兼容性,可以作为旧版本的replica,然后切换为主节点,也就可以完成平滑的升级。新的版本,支持MySQL 8.0和PostgreSQL 13版本。
    • 该功能的客户价值是非常明显的:在更多的业务场景中,可以帮助用户降低成本,同时也可以帮助应对更多的突发流量。另外,云计算的”使命”之一是通过统一的底层资源调度,提升资源利用率,降低资源使用成本,而该功能,在交易数据库的场景,把这个”使命”的粒度降低到了”秒”级别。用好了该功能,在很多场景中,降低50%的数据库成本应该是容易的。
    (more…)
  • 重要更新

    TiDB发布了6.0.0版本,TiFlash也正式开源。另外,近期注意到北京银行和中国银联都有与TiDB相关的采购,相信这些项目应该是有了重大进展,能够进入这些银行的生产系统,对一个新的数据库来说应该是重大的里程碑,数据库开发者们,加油!

    Google Cloud发布新产品BigLake,可以帮助用户在统一的平台上使用BigQuery进行湖/仓数据分析,底层则支持多家云厂商,包括AWS、Azure等。GCP希望通过该产品的集成能力以及BigQuery的分析能力,向用户提供统一的接入和分析层,同时向上层数据产品提供统一的数据接口。GCP的云战略和其他云厂商是非常不同的。

    MongoDB近期和AWS签署了一个长期的合作协议,帮助线下用户更好的迁移到Atlas on AWS;Google发起了Data Cloud Alliance,MongoDB等数据存储、分析、服务等厂商加入。MongoDB大概是第三方数据库厂商与云厂商竞合的”标杆”了。

    OpenGauss 发布3.0.0版本。距2.0.0版本发布约一年时间,新的版本在高性能、高可用、高安全、高智能、工具链等基础能力上持续增强。目前,从外部来看,OpenGauss生态和发展是比较良性的,基于OpenGauss的经认证的数据库有:MuDB、Vastbase、MogDB等。

    最近,X-Paxos也正式开源,这是阿里内部多个数据库产品的基础组件之一,有比较高的成熟度。不过,国内云厂商开源,一直都缺乏与商业的联系,也就难以持续投入,”诸君多努力”吧!。

    腾讯云发布新产品数据库备份(DBS),向用户多云环境数据库的连续数据保护、备份服务。是非常不错的产品,但是,总的来说,好卷…

    更新详情

    • [阿里云] RDS SQL Server企业集群版支持备库可读。
    • [阿里云]  RDS SQL Server CloudDBA支持深度检测功能。
    • [阿里云] 阿里云发布韩国数据中心。
    • [阿里云] X-Paxos正式开源。
    • [阿里云] PolarDB MySQL支持通过OSS外表访问OSS数据。
    • [腾讯云] TDSQL PostgreSQL的Oracle兼容功能开始邀请测试。
    • [华为云] 云数据库 GaussDB(for MySQL)配置和修改内网地址。
    • [AWS] Amazon Athena(Iceberg)的ACID功能正式GA。
    • [AWS] Aurora PostgreSQL通过Foreign Data Wrapper支持连接到SQL Server和Sybase。
    • [AWS] DocumentDB (MongoDB)版本开始支持性能洞察功能。
    • [AWS] RDS 计划不再支持Oracle 12c,并计划帮助用户自动升级到19c。
    • [AWS] RDS Proxy支持了Aurora PostgreSQL 13。
    • [Azure] 发布Arm-based处理器(Ampere Altra)的VM实例。
    • [Azure] SQL DB支持在DMV系统视图中查看数据库恢复任务的详细进展情况。
    • [Azure] Cosmos DB优化建议支持分区键的最优选择建议。
    • [GCP] Google发布新产品BigLake(Preview),帮助用户在统一的平台上使用BigQuery进行湖/仓数据的分析
    • [GCP] Cloud SQL Insights支持MySQL(preview)。
    • [GCP] Google发起”云数据联盟”,包括了databricks/mongodb/redis/埃森哲等。
    • Bytebase 正式商业化,Bytebase是一个独立的、开源的、数据库变更版本管理产品.
    • [DataStax] Astra DB发布新的CDC特性,帮助用户便利同步数据到周边系统中。
    • [Oracle] 发布MySQL Shell for VS Code可以连接并在数据库中执行SQL。
    • [TiDB] 发布6.0.0版本,将新增或增强了Placement Rules in SQL、诊断、MPP计算、可用性(CDC、DM)、企业级数据库管理平台等方面能力;另外,TiFlash也正式开源。
    • [OceanBase] 发布在江西人社养老统筹系统的实践。
    • [openGauss] openGauss 3.0.0 版本正式发布。
    • [Oracle] MySQL通过HeatWave引擎提供ML能力,帮助开发者在MySQL中使用机器学习能力。
    • [MongoDB] 云平台Atlas支持在GCP上以”pay-as-you-go”方式使用MongoDB。
    • [MongoDB] MongoDB与AWS签署了一个6年的合作协议,旨在帮助用户更好的迁移到Atlas on AWS。

    其他

    Atlassian发生一个持续一周并且还未修复的服务终端,受影响服务包括Jira、Confluence、Opsgenie Cloud等,受影响客户约400个(总客户数的0.18%)。目前,还在持续修复,当前声称的是一个维护脚本导致的。

    最后,上海加油,其他也不知道该说什么,哎。

  • 最近,都在和Ningoo一起搞《高性能MySQL 第四版》的翻译工作,以至于行业动态已经拖了将近三个月没有更新了。那,今天,就一起来看看在2022年的第一个季度各个厂商有什么进展吧(是的,2022年第一个季度就要结束了…)。

    重点更新

    • Azure Data Studio持续更新,发布了Table Designer、Query Plan Viewer等功能。虽然,SQL Server最权威的管理工具一直是SSMS,不过最近看到MS也在快速更新Azure Data Studio。相比,SSMS,ADS是一个跨平台的产品,可以同时支持Windows、MacOS、Linux,可以看到MS在以云为战略核心之后,开发者、开放、开源都是其核心策略。
    • 战争还没有结束,更多的数据库相关的大小组织勇敢的表达了自己的观点:
      • Percona’s Stance on Ukraine – Percona Database Performance Blog
      • We stand with Ukraine – MariaDB.org
      • Oracle suspends operations in Russia, SAP pauses sales – REUTERS
    • 火山引擎,自去年12月发布之后,也在快速迭代,最新发布了PostgreSQL的支持,不过,即现在记住火山引擎官网的域名还是有点难度的,不打算改吗?www.volcengine.com 你们都记得住吗?
    • AWS发布自己的JDBC for MySQL,并推荐客户使用,在全力推Aurora的情况下,又推出自己的JDBC,是在准备随时和Oracle全面脱钩吗?
    • AWS RDS通过类似半同步复制的机制,也推出三节点形态,相比EBS复制,这种逻辑复制可以让Standby有更好的性能,同时可以直接提供读服务。

    更新详情

    • [AWS] RDS Multi-AZ Cluster新增更多区域支持
    • [AWS] RDS开始支持 Oracle 21c
    • [AWS] AWS JDBC for MySQL正式GA
    • [AWS] RDS MariaDB开始支持延迟复制
    • [AWS] MemoryDB for Redis开始支持 PrivateLink
    • [AWS] RDS开始支持PostgreSQL 14
    • [MariaDB] 10.9版本发布,将增强JSON支持、异步redo等
    • [Azure] Microsoft Defender支持保护Cosmos DB
    • [Azure] Cosmos DB开始支持MongoDB 4.2 API
    • [Azure] Azure Data Studio发布了Table Designer、Query Plan Viewer
    • [GCP] Memorystore for Redis发布Read Replicas、RDB Snapshots等功能
    • [GCP] Spanner发布了Optimizer v4,提升了二级索引、哈希JOIN等相关功能
    • [GCP] Cloud SQL for MySQL支持了8.0.26,并作为默认版本
    • [GCP] Cloud SQL for SQL Server支持了跨区域的副本
    • [GCP] Cloud SQL for SQL Server 2019成为默认的SQL Server版本
    • [阿里云] AnalyticDB PostgreSQL发布跨实例数据共享
    • [阿里云] AnalyticDB PostgreSQL发布Serverless实例类型
    • [阿里云] RDS MySQL只读实例支持开启binlog
    • [阿里云] RDS PostgreSQL 14大版本发布
    • [阿里云] RDS PostgreSQL 支持机器学习MADlib插件
    • [阿里云] 图数据库GDB自动机器学习组件发布
    • [阿里云] Tair(Redis企业版)现已经开放TairTS时序数据结构、TairCpc数据结构
    • [腾讯] TDB for MySQL支持了连接池功能
    • [腾讯] TDB for SQL Server支持了数据库维度多任务并行、备份数据开始商业化计费
    • [腾讯] TDB for PostgreSQL支持了跨可用区容灾、克隆实例、跨可用区创建只读实例等功能
    • [腾讯] TDB for Redis支持了全球复制功能
    • [腾讯] TDSQL-C MySQL 8.0版本增加了只读节点等功能
    • [腾讯] TDSQL PostgreSQL推出Oracle 兼容版的集中式版
    • [腾讯]  DTS支持了跨账号实例间数据同步,支持了更多的源/目标的组合
    • [华为云] GaussDB(for Mongo)提供了多种数据迁移方案
    • [华为云] GaussDB(for Redis)包周期(类似于包年包月)实例支持规格变更
    • [华为云] 数据复制服务 DRS 实时同步支持DB2 for LUW 10.5、11.5、PostgreSQL->Kafka等
    • [火山引擎] 云数据库 PostgreSQL 版正式发布上线

    另外,原来的个人账号更新都会转移这个账号上,希望更多人以更专业方式来维护,欢迎大家订阅与转发。

  • SQL Server的用户体系和MySQL有非常大的不同,无论是在使用上、还是概念上。所以,这里梳理一下SQL Server的用户与认证的一些基础概念与使用。另外,这个概念在SQL Server相关资料中各个地方都会出现,是理解权限体系的基础。

    “login”“database user”

    在SQL Server中,”login”不是一个动词,而是一个”名称”(注:”log in”是动词),代表的是一个用于登录的对象(Object),这是一个服务器级别的对象,所以,它有自己的登录名(login name)、密码、默认语言、认证方式等。需要强调的是,它不是一个数据库(database)级别的对象。

    而”Database User”是一个数据库级别的对象,与之相对应的则是数据库级别的权限。”Database User”并不能连接或者登录SQL Server实例,所以,一般来说,也不需要密码。

    “login”因为是Server级别的,所以权限也都是Server级别的。本身不能赋予任何数据库相关的权限,但是,login可以和一个Database User建立映射,使用该login连接数据库的时候,该连接也就可以根据Database User权限进行相关的操作了。

    最常见、最简单的创建login和database user的命令如下:

      use zzxdb2;
      create table t_1(id int,nick nchar(12),birthday date);
    
      create login zzxdb2 with password='zzxdb2' ,CHECK_POLICY=OFF;
      create user zzxdb2 for login zzxdb2;
    
      -- 当没有赋予权限的时候,zzxdb2可以登录SQL Server,但是看不到zzxdb2下面的TABLE
      -- 所以,最后还需要赋予database user相应的权限,如下
      exec sp_addrolemember 'db_owner', 'zzxdb2'; 

    为什么容易混淆

    通常的系统中只有用户的概念,权限系统都是基于用户。而SQL Server在其上新增了Login这一层,与其他的系统都不同。另外,在一般的客户端中,在需要登录的时候,通常都是使用”user name”/”password”作为登录认证的凭证,而不是”Login”/”password”,所以初学者通常容易混淆,例如微软的Mac客户端Azure Data Studio:

    一些可以帮助理解”login”和”user”关系的一些问题

    1. 只创建login,而不map到一个具体的database用户,是否可以登录?

    答案是简单的:可以登录,但是没有数据库相关的权限。测试如下:

    先创建一个没有映射到”user”的”login”:

    CREATE LOGIN alogin WITH PASSWORD = 'alogin', CHECK_POLICY=OFF;
    -- 注: CHECK_POLICY可以让你设置简单密码,并不建议加上
    • 使用上面的”login”在Azure Data Studio中连接并进入SQL Server。可以看到,可以正常登录,但是因为没有database相关的权限,所以展示database里面的对象的时候,会失败,如下:

    也就说,”login”只有在与具体的某个database user建立了mapping之后,才可以访问对应的数据库。在上面例子中的”login”主体”alogin”,要访问和管理数据库9zcloud,是会失败的。

    当然,如果真的需要访问的话,那么我们需要先建一个database user,并在user和login之间建立mapping,具体操作如下:

    CREATE USER a_db_user_9zcloud FOR LOGIN alogin;  

    2. 创建用户,不映射到任何login,后续是否还可以重新映射?

    如果在用户创建的时候显式的声明,不映射到任何login,那么后续是否还可以重新映射到某个login?答案似乎没有那么明显了。遂测试如下:

    CREATE USER a_db_user_9zcloud WITHOUT LOGIN;
    ALTER USER  a_db_user_9zcloud WITH LOGIN='alogin';
    -- 报错如下:
    
    消息 33016,级别 16,状态 1,第 45 行
    The user cannot be remapped to a login. Remapping can only be done for users that were mapped to Windows or SQL logins.

    可见,如果在创建的时候显示声明不映射到任何”login”,那么就不能够再重新映射任何的”login”。

    3. 如果用户名和login主体名字不一样,客户端登录的时候使用哪个?

    答案是显然的,但是还是验证一下。

    具体的,如果数据库用户名和login用户名不一样,那么在登录连接SQL Server的时候,使用的是database user还是login的名称?具体看下面的例子,在使用客户端登录的时候,使用的alogin,还是使用a_db_user_9zcloud?

    CREATE LOGIN alogin WITH PASSWORD = 'alogin', CHECK_POLICY=OFF;
    CREATE USER a_db_user_9zcloud FOR LOGIN alogin;

    答案,当然是使用login的主体alogin。

    4. 在创建用户时如果映射到了某个login,同时也创建密码,那么这个密码有什么用?

    是啊,有什么用呢? 具体的,在创建用户时映射到某个具体的login,但是依旧指定一个密码,那么这个密码有什么用?测试验证如下:

    CREATE LOGIN alogin WITH PASSWORD = 'alogin', CHECK_POLICY=OFF;
    CREATE USER a_db_user_9zcloud FOR LOGIN alogin WITH PASSWORD = 'dbuser9zcloud';

    答案:你就不能这么用!!(注:仅当在contained database中可以使用密码,参考) 在明确映射到某个具体的login的用户,不需要密码,也无法指定密码。所以,上面的语句执行会失败,报如下错误:

    消息 33234,级别 16,状态 1,第 47 行
    
    The parameter PASSWORD cannot be provided for users that cannot authenticate in a database.

    另外,注意到login在创建的时候,是可以指定默认数据库(DEFAULT_DATABASE)的;创建用户的时候,可以指定默认的schema。

    其他内容

    • 在给一个对象(主体)赋权的时候,可以通过按照细粒度(某个表的某种权限)方式进行,也可以直接将其加入到某个角色组,那么这个角色组对应的权限就都有了。例如,将login加入到”sysadmin”(fixed server role),那么就有了所有sysadmin角色组的权限,sysadmin可以理解是一个超级权限组,如果在该组中,那么访问对象时不需要检查该账号的权限;与sysadmin对应的一个权限是”CONTROL SERVER”,如果使用GRANT则可以使用这个权限。
    • 另外,前文中偶尔会用到”主体”这个名称,英文对应SQL Server文档中的”Principals”,”主体”是SQL Server官方中文文档的翻译(参考)。可以理解为一个实体,或者前面对象的实例化或者实体,也就是说,某个具体的”server roles, logins, database roles, or users.” 都可以称作”Principals”。
    • SQL Server中的系统表sys.server_principals、sys.server_permissions会存储相关的元数据。
    • 在SQL Server官方文档中将”login”翻译为”登录名”(参考)。这也是为什么,一些客户端在让输入用户名的时候,其实是输入一个login主体名和对应的密码。
    • 在创建user的时候,如果没有显示的指定FOR LOGIN,没有指定WITHOUT LOGIN,那么该user将会被映射到同名的login上(还没有验证这一点,参考:If FOR LOGIN is omitted, the new database user will be mapped to the SQL Server login with the same name.)。
    • 另外,系统中还有一个名字为guest的login,默认是不可用的。
    • 在实际中,也有一些场景是需要创建user,而不映射到任何的login,后续会再考虑介绍这类场景。

    参考阅读

    • Determining Effective Database Engine Permissions:链接 如何查看系统中的账号权限
    • Database Engine Permissions SQL Server 2017 and Azure SQL Database: 链接
  • 选择

    ·

    在前公司的时候,参加过一个叫《选择》的培训(参考),与其说这是一个关于管理的培训,倒不如说这是一个认识自己,认识人与人关系的培训,其背后的意义,并不仅仅适用于公司协作,更多的是在生活中,如何与自己”和解”,如何与他人”和解”。在这个课程中,当时的培训老师叫”龙子立”(参考),他在介绍中,介绍了什么是”价值观”,为什么”价值观”需要用具体的事情和衡量,为什么价值观需要付出代价。

    “付出”有时候是试金石

    付出就是一颗”试金石”。根据生活中的经验,通常,每个人都深深的认为自己是一个好人,是一个善良的人。但是,如果,试问:你今年有没有帮助过你的朋友或者其他人?无论事情大小。例如,

    • 驾车时,斑马线一侧有人在左右张望,而你可以通过的情况下,你是否愿意停下车来等他?
    • 常用的服务/软件/产品的体验调研,你是否愿意花十分钟认真的完成?
    • 如果你是一个资深的技术人员,你用过很多的开源软件,你有没有帮助过这个软件?
    • 你会不会为你经常使用的软件,而慷慨付费?
    • 你有没有帮助过陌生人,无论事情大小?
    • 你是否会由衷在他人面前/背后,因为认可而夸赞他人?
    • 你是否会由衷的认可与你意见相左的人的一些行为或者做法?”

    再比如:

    • 当你有权责的时候,你是否会借此伤害(或大或小)曾经让你”怒目”的人?
    • 当你有能力的时候,你是否愿意帮助那些曾经让你“怒目”的人?
    • 当你意识到你错了的时候(有时候也许你是对的),你是否敢于向你曾经言语伤害到的人道歉?

    再比如:

    • 当你在游戏/追剧正酣时,是否愿意为了孩子找不到一块积木而停下?
    • 你是否愿意为了带孩子去动物/植物园,而放弃周末早上温暖的被窝?
    • 你是否愿意花几个小时/几百块,为爱人挑选一个礼物(也许她不一定喜欢)?
    • 你是否愿意花几个小时/几百块,在重大节日(例如新年)为大家准备一份节日惊喜?

    无论上面哪件事情,你都需要付出代价,或大或小,有时候是几分钟时间、有时候是几个小时,有时候是几十块钱,有时候是几千块或者更多。如果你从不曾做过一件帮助他人的事情,那么大概很难说服自己,自己是一个善良的人。

    不以善小而不为,不以恶小而为之

    这是”刘皇叔”大约两千年前写给儿子的”要求”,却从不曾过时。如果每个人都要求自己能够做出惊世骇俗之举,显然是不可能的,从善也是如此,每个人只能从小事开始。实际上,如果在小事上做到善良,那么遇到大事/大节,则也更可能做出善良的选择。反之亦然,”小恶”做的多了,自然更容易一步步走向”大恶”。

    在实际生活中,能够做一些”小善”便已经很好了,例如,能够在斑马线前停下来等待行人优先通过,能够停下来耐心的为快递小哥带路到”春晓苑”,为自己经常使用的软件付费等。

    这一次做个善良的人,不纠结于以前,也不要为以后背负任何负担

    做善良的事情并不容易。我们通常会屈服于各种各样的理由,很多理由似乎都没有任何道理。在骑电动车的时候,来到一个红灯路口,同时现在穿过也很安全的时候,以前经常会纠结:“我昨天就没有等这个红灯,今天要充什么好人”。现在,我则反过来激励自己:“虽然,我昨天没有等这个红灯,也许我明天也不会等这个红灯,这并不妨碍我这一次,这一刻做一件正确的事情”。事实上,这么想,这么做,骑电动车时闯这个红灯的次数少了很多。

    这是一个建议,一个选项,而不是一个“人设”

    近几年,“人设崩塌”事件时有发生,做个善良的人的人设则更难维持(似乎是不可能),所以,这不是一个人设,而是一个建议,今天做一个好人,做个善良的人,做一件善良的事情,并不要求自己永远都这样,每个人的经历、所处的环境通常都非常复杂,甚至还有很多是刻在基因中的选择倾向,做一个“自私”人的同时,并不影响依旧去做一些善良的事情,做了一些善良的事情,那么这件事情上,你就是一个善良的人,我不要求自己一直能够做一个善良的人,而且我也很确定,任何人都很难这样。

    我不想,不打算背负任何“好人”的人设负担,但我依旧愿意做好这一件善良、正确的事情。

    好人不一定有好报,但是,依旧做一个好人

    虽然,社会舆论会不断的渲染,因为做了好人,会可能获得更好的结果,但是实际的情况是,影响是否会有“好报”的因素,非常多,而你自己是不是一个好人,只是一个非常小的因子。一件事情,是不是有好报,个人做个粗略的判断,运气大概占了四层,个人努力可能占了三层,另外,还有三层大概是更多的不可知,或者不确定的因素。至于,你是不是一个好人,在其中的影响甚微。虽然,法律、道德等,都会尽量将社会引导到好人好报、恶人恶报,但是,非常非常遗憾,好人也会有恶报,恶人也会有好报,这几乎是一定的。

    所以,选择做一个好人,不能纠结于此,也不能因为好人没有获得好报而放弃,也不能因为恶人没有恶报,而忿忿。

    善良的分寸

    尽自己的绵薄之力帮助他人,就非常不错了。如果愿意付出更多,已经是侠义心肠了。给自己订立的“分寸”有两个原则,其一,对自己生活没有什么影响,受助者也只是需要基础的帮助。

    其二,付出一份,最好能够给他人带来更多收获。例如,拿出 100 元帮助边远地区贫困学子,于自己可能是较小的付出,但是于他人,则是几个月的生计、是一份安心就学保障,自然就达到了一份付出,更多收获的效果。

    如丰子恺所在“不宠无惊过一生”中提到,“不乱于心,不困于情。不畏将来,不念过往”。

  • 这是一个记录。虽然微软的文档已经非常完善和友好了,但是涉及到一些软件版本等相关问题,配置并不畅通。

    安装

    本地环境是macOS Big Sur 11.4版本,使用的是Python 3.8.2版本。

    zzx@localhost % python3
    Python 3.8.2 (default, Apr  8 2021, 23:19:18)
    [Clang 12.0.5 (clang-1205.0.22.9)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>>

    需要安装pyodbc、unixodbc、msodbcsql17、mssql-tools等工具(详细参考):

    pip3 install pyodbc
    brew install unixodbc

    测试脚本

    主要参考微软文档:Proof of concept connecting to SQL using pyodbc。测试连接脚本如下:

    import pyodbc
    # Some other example server values are
    # server = 'localhost\sqlexpress' # for a named instance
    # server = 'myserver,port' # to specify an alternate port
    server = 'x.x.x.x'
    # server = 'tcp:x.x.x.x,1433'
    database = 'xxx'
    username = 'xxx'
    password = 'xxx'
    cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+ password)
    cursor = cnxn.cursor()
    
    #Sample select query
    cursor.execute("SELECT @@version;")
    row = cursor.fetchone()
    while row:
        print(row[0])
        row = cursor.fetchone()

    一下子就跑通了? 有经验的开发者都知道,那当然不能这么顺利,是吧。首先,遇到如下报错:

    Traceback (most recent call last):
      File "mssqlremotessh.py", line 10, in <module>
        cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};SERVER='+server+';DATABASE='+database+';UID='+username+';PWD='+ password)
    pyodbc.OperationalError: ('08001', '[08001] [Microsoft][ODBC Driver 17 for SQL Server]Client unable to establish connection (0) (SQLDriverConnect)')

    是哪个环节的问题?

    老实说,这个报错真的很不友好,无法看出来是什么地方的问题。首先,根据Github上一个issue建议首先通过isql命令(应该是unixODBC的工具)尝试连接一下SQL Server,果然有了新的发现:

    # 注意:下面命令的IP和密码都被修改了
    isql -v -k 'Driver={ODBC Driver 17 for SQL Server};Server=tcp:18.336.80.202,1433;Database=9zcloud;Uid=zzx;Pwd=********;'
    
    
    [08001][Microsoft][ODBC Driver 17 for SQL Server]SSL Provider: [OpenSSL library could not be loaded, make sure OpenSSL 1.0 or 1.1 is installed]
    [08001][Microsoft][ODBC Driver 17 for SQL Server]Client unable to establish connection
    [ISQL]ERROR: Could not SQLDriverConnect

    解决openssl版本依赖问题

    看起来似乎是ODBC依赖OpenSSL 1.0或者1.1,而查看了本地默认安装的应该是v3版本,查看如下:

    $ cd /usr/local/Cellar/ && ls
    $ cd openssl@3/3.0.1/bin
    $ ./openssl version
    $ OpenSSL 3.0.1 14 Dec 2021 (Library: OpenSSL 3.0.1 14 Dec 2021)

    自此,已经找到了问题的症结(也可能是问题的症结之一,是吧):似乎是ODBC只认这两个版本的openssl,沿着此线索搜索,发现,这个问题在Github的 issue 59@microsoft/homebrew-mssql-release 中讨论得比较多,而且,在下面的回答中也有一些办法可以尝试解决:在系统中,额外在安装openssl 1.1,并把链接库目录的软连接从3.0版本更换到1.1版本。(这么做,还是有点担心其他的软件运行有问题的,但是先这么做吧,把问题解决了),详细回答参考如下:

    具体的操作如下:

    zzx@localhost ~ % ls -lah /usr/local/opt/openssl
    lrwxr-xr-x  1 zzx  admin    25B 12 28 10:21 /usr/local/opt/openssl -> ../Cellar/openssl@3/3.0.1
    
    unlink /usr/local/opt/openssl
    
    # 这里要注意,你所安装的openssl版本和目录可能和以上截图中是不同的,所以要根据实际情况进行连接,例如我这里是1.1.1m版本,而不是截图中的1.1.1l版本。
    ln -s /usr/local/Cellar/openssl@1.1/1.1.1m /usr/local/opt/openssl

    Finnally,it works!!

    zzx@localhost ~ % ln -s /usr/local/Cellar/openssl@1.1/1.1.1m /usr/local/opt/openssl
    zzx@localhost ~ % isql -v -k 'Driver={ODBC Driver 17 for SQL Server};Server=tcp:19.36.80.2,1433;Database=9zcloud;Uid=zzx;Pwd=******;'
    +---------------------------------------+
    | Connected!                            |
    |                                       |
    | sql-statement                         |
    | help [tablename]                      |
    | quit                                  |
    |                                       |
    +---------------------------------------+
    SQL> select * from dbo.t_1;
    +------------+---------------------------------+-----------+
    | id         | nick                            | birthday  |
    +------------+---------------------------------+-----------+
    | 1          |                                 |           |
    | 2          | zzx                             |           |
    | 3          | yzs                             | 2008-09-23|
    +------------+---------------------------------+-----------+

    在回头去运行,最前面的示例脚本,也可以正常连接SQL Server,至此,剧终。所以,回头来看,今天的解决问题的堆栈如下:

    • unixODBC关于openssl版本兼容性的问题
    • 安装unixODBC & mssql-tools
    • 尝试python连接SQL Server
    • 尝试通过ssh tunnel连接SQL Server

    相关阅读

    • 更多关于什么是unixODBC,什么事isql,可以参考:unixODBC
    • Install the Microsoft ODBC driver for SQL Server (macOS):参考