写点什么

昆仑数据库 MySQL 连接协议简介

作者:KunlunBase
  • 2022 年 7 月 12 日
  • 本文字数:5684 字

    阅读完需:约 19 分钟

昆仑数据库的计算节点基于 PostgreSQL 研发,因而直接可以支持 PostgreSQL 的连接协议,所以使用 JDBC、ODBC 等通用的数据库连接协议以及使用各类编程语言的 PostgreSQL 专有的连接库的软件都可以连接到昆仑数据库集群并且正常工作。


为了让原本使用 MySQL 的应用程序可以不需要修改也不需要重新编译就能连接并且正常使用昆仑数据库,我们开发了昆仑数据库的 MySQL 连接协议,本文对此协议实现做一个简介。


总的来说,对于 KunlunBase 来说,连接协议就是客户端与 KunlunBase 服务器通信的管道,MySQL 和 PostgreSQL 协议就是两种形状不同的管道,而其中传输的 SQL 语句和查询结果则本质上是相同的。


也就是说 KunlunBase 支持的任何 SQL 语法和功能都可以在 MySQL 和 PostgreSQL 这两种连接协议中的任何一种连接中传输到服务器集群中正常执行并收到其结果。


例如可以在 MySQL 连接中发送 PostgreSQL 私有语法 SQL 或者标准 SQL 语句,包括 prepared statement 语法、存储过程语法、DDL 语法等,并且得到遵循 MySQL 协议的结果,从而可以使用 MySQL 客户端库完成结果读取;也可以 在 PostgreSQL 连接中发送 KunlunBase 支持的任何 MySQL 私有语法(例如 prepared statement、DML 等)的 SQL 语句或者标准 SQL 语句,并且得到遵循 PostgreSQL 的结果,从而可以使用 PostgreSQL 客户端库完成结果读取。

昆仑数据库 MySQL 协议支持的功能

昆仑数据库 MySQL 协议支持所有常用功能,包括文本和二进制协议,连接验证(只支持 mysql_native_password),数据压缩,prepared statement,字符集,错误处理,SSL 连接等。


一个 Kunlun-server(计算节点)同时监听 2 个 TCP 端口 --- PostgreSQL 协议的端口(默认 5432)和 MySQL 协议的端口(默认 5306),都可以通过配置文件自定义配置。


MySQL 和 PostgreSQL 客户端使用统一的用户名和密码连接 Kunlun-server,不论使用哪一种连接协议,Kunlun-server 收到 TCP 连接请求后,会启动本端口的服务端协议(即 PostgreSQL 或者 MySQL)处理模块,完成连接验证,建立起有效的数据库连接。


后续在这两类连接中用户可以发送的 SQL 语句完全相同,与协议无关。


用户可以在任何一类连接中发送标准 SQL 语句,或者 PostgreSQL 或者 MySQL 私有语法的 SQL 语句给昆仑数据库并且获得结果。

账号和访问控制

用户通过 Kunlun-server 的 PostgreSQL 或者 MySQL 连接发送 create user 语句建立用户账户,这里的 create user 语法(以及任何其他 DDL 语法)必须是 PostgreSQL 的语法。


DBA 通过在 pg_hba.conf 配置文件中建立访问控制规则,来可选地定义某些用户账号必须来自特定的 IP 或者域名,或者某个账户只能访问某些 database 等访问控制规则。


关于在 pg_hba.conf 配置访问控制规则,详见 PostgreSQL 的文档。

错误处理

昆仑数据库 MySQ L 协议会自动把 PostgreSQL 的错误号被映射到对应的 MySQL 错误号;MySQL 协议运行期间返回的错误则使用与 MySQL 的 server 端协议实现完全相同的错误号。


因此应用程序原本处理 MySQL 错误的代码逻辑不需要任何修改就可以按照预期工作。


JDBC 等数据库客户端 API 库基于异常类树进行错误处理,每一个异常类型绑定若干个 MySQL 错误号,因此只要应用程序代码实现了异常捕捉,也可以正确地捕获昆仑数据库的 MySQL 连接返回的错误异常。


错误描述文本使用 PostgreSQL 的错误字符串,而不是 MySQL 错误号对应的文本。


这通常不会成为问题,因为根据 MySQL 的文档,虽然错误号码在所有 MySQL 版本中不变,但是错误描述并不承诺不变,所以应用程序本来也不应该基于错误字符串的内容匹配来实现其功能逻辑。


另外,KunlunBase 支持 MySQL 的 SHOW WARNINGS 和 SHOW ERRORS 语句,并且其用法和效果与 MySQL 的相同语句完全相同。

字符集

MySQL 客户端可以按照其标准方式指定字符集,这个字符集如果昆仑数据库不支持则连接失败报错。


PostgreSQL 默认支持丰富的字符集,它与 MySQL 支持的字符集大部分是重合的,所有常见字符集两者都支持,包括所有中文、日韩字符集以及主要欧洲(西中东欧)各语言字符集。


MySQL 客户端发送到昆仑数据库的任何字符串,都会先转换为当前数据库的字符集再使用;返回给 MySQL 客户端的任何字符串都会先从当前数据库的字符集转回 MySQL 客户端字符集再发送。


不支持 MySQL 的 set client/connection/server_character_set/collation,但是支持 SET NAMES 语法。

数据压缩

支持使用 zlib 和 zstd 在传输数据包之前压缩。

昆仑数据库 MySQL 连接协议不支持的 MySQL 功能

只支持 mysql_native_password 一种认证方法,不支持其他认证方法或者外部认证插件。这对于自 mysql-4.1 以来的各个版本的 MySQL 客户端都是没问题的,它们都可以正确地连接上来并正常工作。

所有的密码管理功能:

包括密码过期,密码验证,双密码,密码重用限制,多次密码错误导致账户临时锁定等。所有此类功能都使用 PostgreSQL 原有的功能。

账户管理的不常用功能:

代理用户(proxy user),未知、匿名用户、账户锁定,账户资源限制。

使用 text 协议发送 prepared statement:

生产系统中应该使用 binary 连接执行 prepared statement,这才是其设计初衷,也是昆仑数据库的 MySQL 协议支持的。


text 协议执行 prepare/execute 命令无论对于 MySQL 还是 PostgreSQL 都仅仅是用于开发和调试,而昆仑数据库并不支持 mysql 的 prepare/execute 语法,并且没有 MySQL 的用户自定义变量这个功能,也就无法按照 mysql prepare statement 的方式绑定参数。

init_connect 语句初始化连接状态:

该功能知道的用户很少,而且在连接 初始化好之前执行 SQL 语句本来也不符合数据库系统的设计原理,因此在昆仑数据库中不支持。

session state tracking:

因为 MySQL 维护的那些 status 变量,在昆仑数据库的计算节点中并不存在。因此也不支持 mysql_session_track_xxx 系列客户端 API 函数。


但是同时,昆仑数据库继承了 PostgreSQL 的 pgstat 基础设施,pgstat 可以收集非常丰富的系统运行时统计信息,MySQL 和 PostgreSQL 客户端都可以通过查询 pgstat 的一系列视图和函数,可以得到这些信息。


详见 PostgreSQL 的 pgstat 文档。

昆仑数据库 MySQL 服务端协议与 MySQL 服务端协议不同的功能

连接的目标数据库

当 MySQL 客户端连接昆仑数据库计算节点时没有指定数据库名称,那么默认连接到 “postgres” 数据库,这一点与 MySQL 的行为是不同的 --- MySQL 在这种情况下不指定当前数据库。


同时,MySQL 支持使用 use db 语句或者使用 mysql_select_db()客户端 API 来切换当前数据库,但是 postgres 并不允许在一个活跃连接中切换数据库,详见下文。

数据输出格式

对于所有数据类型,昆仑数据库都使用 PostgreSQL 的输出函数来生成文本协议下的查询结果,这意味着 decimal/numeric, float,real(double), date, timestamp, timestamptz, time 类型的输出结果在个别情况下可能会与 MySQL 的输出的字段值文本表示有细微差别 --- 由于数值类型是因为序列化的浮点数精度差异;日期时间类型是因为 locale 设置或者时区信息,例如 PostgreSQL 的 timestamptz 类型字段值总是带有时区值,例如”2022-5-30 21:08:35+08”。


如果使用 binary 协议(也就是使用 prepared statement,bind 参数和结果),则没有这些差别。

昆仑数据库支持的 MySQL 命令

在昆仑数据库的 MySQL 连接中,MySQL 客户端软件除了可以发送 SQL 语句(即 COM_QUERY 命令)之外,还可以发送若干种其他命令,具体包括:

改变连接状态的命令及其对应的 MySQL 客户端 API:

COM_SET_OPTION:mysql_set_server_option()COM_RESET_CONNECTION:mysql_reset_connection()COM_PING:mysql_ping()COM_QUIT:mysql_close()
复制代码

Prepared statement 相关的命令:

COM_STMT_EXECUTECOM_STMT_FETCHCOM_STMT_PREPARECOM_STMT_SEND_LONG_DATACOM_STMT_RESETCOM_STMT_CLOSE
复制代码

昆仑数据库不支持的 MySQL 命令

昆仑数据库不支持的 MySQL 命令包括所有 deprecated(过时的,即将在未来版本去除)的命令,replication 和 clone 相关的命令,以及 mysql server 内部使用的(客户端不可以使用的)命令。


如果应用程序调用 MySQL 客户端 API 执行下列不支持的命令,则昆仑数据库计算节点会返回标准的 MySQL 错误 1047(不支持的命令)。

昆仑数据库不支持的 MySQL 命令如下:

  • COM_PROCESS_KILL:mysql_kill() 已过时,使用 kill connection/query,不过昆仑数据库目前不支持此命令

  • COM_PROCESS_INFO:

  • mysql_list_processes() 已过时,使用 show

  • processlist,昆仑数据库目前已支持此命令

  • COM_BINLOG_DUMP_GTID:replication 命令,备节点 IO 线程连接主节点时使用

  • COM_BINLOG_DUMP:replication 命令,备节点 IO 线程连接主节点时使用

  • COM_REFRESH:更新用户账户和访问控制信息。昆仑数据库不需要用户显示地刷新缓存,而是完全自动的探测到任何元数据表发生变化并且自动更新缓存的对应信息。不支持此命令或者对应的 mysql_reload(), mysql_refresh()函数

  • COM_STATISTICS:昆仑数据库中统计信息使用 pgstat 的设施获得,不支持 mysql_stat() API 函数或者 mysqladmin 获取统计信息

  • COM_DEBUG:mysql_debug() 函数,仅在开发人员调试时使用,生产系统中无法使用。

  • COM_REGISTER_SLAVE:replication 命令,备节点 IO 线程连接主节点时使用

  • COM_CLONE:clone 命令

  • COM_FIELD_LIST:mysql_list_fields()已过时,使用 show columns,不过昆仑数据库目前不支持此命令,用户需要查询 pg_attribute 等元数据表获得列的元数据

  • COM_SLEEP:不是客户端发送的,内部使用

  • COM_CONNECT:连接建立后就不可以发送此命令

  • COM_TIME:不是客户端发送的,内部使用

  • COM_DELAYED_INSERT:在 mysql 中已去除

  • COM_END:不是客户端发送的,内部使用

  • 不支持 mysql_set_local_infile_xxx()系列函数

切换会话当前数据库和用户命令:

COM_INIT_DB:在 MySQL 连接中切换当前数据库,也即是 use db 语句的命令版本。在昆仑数据库中这两种方式切换 database 都不支持。


PostgreSQL 要求客户端连接到一个 database 后始终使用它,不可以切换。


同时 PostgreSQL 提供了 schema 这个概念,它是一个逻辑层面的名字空间。


在 PostgreSQL 中一个 database 里面可以创建任意数量的 schema, database 和 schema 之外的数据库对象(比如表,索引,视图,存储过程,sequence 等)都一定属于某个 schema(名字空间)。


引用这些数据库对象时候,如果不指定 schema 名称,那么就是在一个称为 search_path 变量的名字空间列表中依次按名字寻找这个对象。在一个连接中可以动态的修改 search_path 变量来修改名字空间查找的 schema 序列,使用 PostgreSQL 的语法 set search_path。


昆仑数据库完全继承了这些特征。在一个 MySQL 连接中如果要切换 schema,那么执行 PostgreSQL 的 set search_path 即可。MySQL 的 database 概念其实是数据库对象的物理(目录存储位置)和逻辑(名字空间)合并为一体了,而 PostgreSQL 则把它们分开,实现了更大的灵活性和自由度。


COM_CHANGE_USER:在 MySQL 中这个命令除了可以切换当前用户之外,还可以切换 database。由于上述原因,我们不支持切换数据库,但是可以切换当前用户,所以只有 mysql_change_user()函数调用指定的 database name 与当前连接已经连接的数据库相同时候,才可以正确执行,否则调用失败返回错误。另外,用户也可以执行 PostgreSQL 的 set session authorization,set role 等命令做用户/角色切换。

MySQL 语法兼容性

  1. postgreSQL 要求标识符名称字节数<64, 意味着如果标识符是中文的话,中文标识符最大字符数 M 在一个范围内变化,最小的 M 不到 20 个字符。这里的标识符包括 database,table,column,procedure 等。

  2. 昆仑数据库支持常用的 MySQL 私有的 DML 语法以及变量读写语法 。并且无论在使用 PostgreSQL 协议的连接还是 MySQL 协议的连接中,都可以执行昆仑数据库支持的任何语法,包括这些 MySQL 私有 DML 语法,也包括标准的 SQL 语法,以及昆仑数据库支持的任何其他 PostgreSQL 私有语法。

  3. KunlunBase 支持 autoincrement 关键字定义列为自增列,也支持 last_insert_id()函数,其用法与 mysql 完全相同

  4. KunlunBase 支持 MySQL 的所有私有数据类型,包括:


  • TINYBLOB, BLOB, MEDIUMBLOB, LONGBLOB, VARBINARY, BINARY

  • 在 KunlunBase 中统一按照 bytea 类型来存储和处理

  • TINYTEXT, MEDIUMTEXT, LONGTEXT

  • 在 KunlunBase 中都统一按照 text 类型来存储和处理

  • DOUBLE (不带 PRECISION)

  • byte, tinyint, mediumint, middleint, 以及所有整形类型的 UNSIGNED 修饰符

  • DATETIME:不带时区信息的时间戳。

  • TIMESTAMP


在 MySQL 和 PostgreSQL 中 TIMESTAMP 类型有不同的意义:在 MySQL 中它表示带有时区信息的时间戳,在 PostgreSQL 中表示不带时区信息的时间戳。为了与二者都保持一致,在 KunlunBase 中,在 MySQL 连接中遵循 MySQL 的定义,在 PostgreSQL 连接中遵循 PostgreSQL 的定义。


  1. 昆仑数据库不支持 MySQL 存储过程或者 MySQL 专有的 DDL 语法以及诸如 show 系列的命令,load data infile 命令等等任何 MySQL 特有功能的语法。

SSL 支持

目前我们还没有实现昆仑数据库 MySQL 协议的 SSL 支持,在未来的版本中会支持 SSL 连接。目前应用程序无法调用任何 MySQL 客户端 SSL API 与昆仑数据库工作。

END

昆仑数据库是一个 HTAP NewSQL 分布式数据库管理系统,可以满足用户对海量关系数据的存储管理和利用的全方位需求。应用开发者和 DBA 的使用昆仑数据库的体验与单机 MySQL 和单机 PostgreSQL 几乎完全相同,因为首先昆仑数据库支持 PostgreSQL 和 MySQL 双协议,支持标准 SQL:2011 的 DML 语法和功能以及 PostgreSQL 和 MySQL 对标准 SQL 的扩展。同时,昆仑数据库集群支持水平弹性扩容,数据自动拆分,分布式事务处理和分布式查询处理,健壮的容错容灾能力,完善直观的监测分析告警能力,集群数据备份和恢复等 常用的 DBA 数据管理和操作。所有这些功能无需任何应用系统侧的编码工作,也无需 DBA 人工介入,不停服不影响业务正常运行。昆仑数据库具备全面的 OLAP 数据分析能力,通过了 TPC-H 和 TPC-DS 标准测试集,可以实时分析最新的业务数据,帮助用户发掘出数据的价值。昆仑数据库支持公有云和私有云环境的部署,可以与 docker,k8s 等云基础设施无缝协作,可以轻松搭建云数据库服务。请访问 http://www.zettadb.com/ 获取更多信息并且下载昆仑数据库软件、文档和资料。

KunlunBase 项目已开源

【GitHub:】https://github.com/zettadb

【Gitee:】https://gitee.com/zettadb

发布于: 刚刚阅读数: 3
用户头像

KunlunBase

关注

还未添加个人签名 2022.03.09 加入

还未添加个人简介

评论

发布
暂无评论
昆仑数据库 MySQL 连接协议简介_国产数据库_KunlunBase_InfoQ写作社区