7.4.2 MySQL¶
Doris JDBC Catalog
支持通过标准 JDBC
接口连接 MySQL
数据库。本文档介绍如何配置 MySQL
数据库连接。
1 使用须知¶
要连接到 MySQL
数据库,您需要
-
MySQL
5.7
,8.0
或更高版本 -
MySQL
数据库的JDBC
驱动程序,您可以从Maven
仓库下载最新或指定版本的MySQL JDBC
驱动程序。推荐使用MySQL Connector/J 8.0.31
及以上版本。 -
Doris
每个FE
和BE
节点和MySQL
服务器之间的网络连接,默认端口为3306
。
2 连接 MySQL¶
SQL | |
---|---|
1 2 3 4 5 6 7 8 |
|
Tip
jdbc_url
定义要传递给 MySQL JDBC
驱动程序的连接信息和参数。支持的 URL
的参数可在 MySQL
开发指南中找到。
2.1 连接安全¶
如果您使用数据源上安装的全局信任证书配置了 TLS
,则可以通过将参数附加到在 jdbc_url
属性中设置的 JDBC
连接字符串来启用集群和数据源之间的 TLS
。
例如,对于 MySQL Connector/J 8.0
版,使用 sslMode
参数通过 TLS
保护连接。默认情况下,该参数设置为 PREFERRED
,如果服务器启用,它可以保护连接。您还可以将此参数设置为 REQUIRED
,如果未建立 TLS
,则会导致连接失败。
您可以在通过在 jdbc_url
中添加 sslMode
参数来配置它:
Bash | |
---|---|
1 |
|
有关 TLS
配置选项的更多信息,请参阅 MySQL JDBC
安全文档。
3 层级映射¶
映射 MySQL
时, Doris
的一个 Database
对应于 MySQL
中的一个 Database
。而 Doris
的 Database
下的 Table
则对应于 MySQL
中,该 Database
下的 Tables
。即映射关系如下:
Doris | MySQL |
---|---|
Catalog | MySQL Server |
Database | Database |
Table | Table |
4 类型映射¶
4.1 MySQL 到 Doris 类型映射¶
MYSQL Type | Doris Type |
---|---|
BOOLEAN | TINYINT |
TINYINT | TINYINT |
SMALLINT | SMALLINT |
MEDIUMINT | INT |
INT | INT |
BIGINT | BIGINT |
UNSIGNED TINYINT | SMALLINT |
UNSIGNED MEDIUMINT | INT |
UNSIGNED INT | BIGINT |
UNSIGNED BIGINT | LARGEINT |
FLOAT | FLOAT |
DOUBLE | DOUBLE |
DECIMAL | DECIMAL |
UNSIGNED DECIMAL(p,s) | DECIMAL(p+1,s) / STRING |
DATE | DATE |
TIMESTAMP | DATETIME |
DATETIME | DATETIME |
YEAR | SMALLINT |
TIME | STRING |
CHAR | CHAR |
VARCHAR | VARCHAR |
JSON | STRING |
SET | STRING |
ENUM | STRING |
BIT | BOOLEAN/STRING |
TINYTEXT,TEXT,MEDIUMTEXT,LONGTEXT | STRING |
BLOB,MEDIUMBLOB,LONGBLOB,TINYBLOB | STRING |
BINARY,VARBINARY | STRING |
Other | UNSUPPORTED |
Tip
-
Doris
不支持UNSIGNED
数据类型,所以UNSIGNED
数据类型会被映射为Doris
对应大一个数量级的数据类型。 -
UNSIGNED DECIMAL(p,s)
会被映射为DECIMAL(p+1,s)
或STRING
。注意在此类型被映射为String
时,只能支持查询,不能对MySQL
进行写入操作。 -
为了更好的读取与计算性能均衡,
Doris
会将JSON
类型映射为STRING
类型。 -
Doris
不支持BIT
类型,BIT
类型会在BIT(1)
时被映射为BOOLEAN
,其他情况下映射为STRING
。 -
Doris
不支持YEAR
类型,YEAR
类型会被映射为SMALLINT
。 -
Doris
不支持TIME
类型,TIME
类型会被映射为STRING
。
4.2 时间戳类型处理¶
在 JDBC
类型 Catalog
读取数据时, BE
的 Java
部分使用 JVM
时区。 JVM
时区默认为 BE
部署机器的时区,这会影响 JDBC
读取数据时的时区转换。
为了确保时区一致性,建议在 be.conf
的 JAVA_OPTS
中设置 JVM
时区与 Doris session
的 time_zone
一致。
读取 MySQL
的 TIMESTAMP
类型时,请在 JDBC URL
中添加参数: connectionTimeZone=LOCAL
和 forceConnectionTimeZoneToSession=true
。这些参数适用于 MySQL Connector/J 8
以上版本,可确保读取的时间为 Doris BE JVM
时区,而非 MySQL session
时区。
5 查询优化¶
5.1 谓词下推¶
-
当执行类似于
where dt = '2022-01-01'
这样的查询时,Doris
能够将这些过滤条件下推到外部数据源,从而直接在数据源层面排除不符合条件的数据,减少了不必要的数据获取和传输。这大大提高了查询性能,同时也降低了对外部数据源的负载。 -
当变量
enable_ext_func_pred_pushdown
设置为true
,会将where
之后的函数条件也下推到外部数据源,Doris
会自动识别部分MySQL
不支持的函数,可通过explain sql
查看。当前
Doris
默认不会下推到MySQL
的函数如下Function DATE_TRUNC MONEY_FORMAT NEGATIVE 当您发现还有其他函数不支持下推时,可以通过
fe.conf
配置jdbc_mysql_unsupported_pushdown_functions
来指定不支持下推的函数。如:jdbc_mysql_unsupported_pushdown_functions=func1,func2
5.2 行数限制¶
如果在查询中带有 limit
关键字, Doris
会将 limit
下推到 MySQL
,以减少数据传输量。
5.3 转义字符¶
Doris
会在下发到 MySQL
的查询语句中,自动在字段名与表名上加上转义符: (``)
,以避免字段名与表名与 MySQL
内部关键字冲突。
6 连接异常排查¶
-
Communications link failure The last packet successfully received from the server was 7 milliseconds ago.
-
原因:
-
网络问题:
-
网络不稳定或连接中断。
-
客户端和服务器之间的网络延迟过高。
-
-
MySQL
服务器设置MySQL
服务器可能配置了连接超时参数,例如wait_timeout
或interactive_timeout
,导致连接超时被关闭。
-
防火墙设置
- 防火墙规则可能阻止了客户端与服务器之间的通信。
-
连接池设置
- 连接池中的配置
connection_pool_max_life_time
可能导致连接被关闭或回收,或者未及时探活
- 连接池中的配置
-
服务器资源问题
MySQL
服务器可能资源不足,无法处理新的连接请求。
-
客户端配置
- 客户端
JDBC
驱动配置错误,例如autoReconnect
参数未设置或设置不当。
- 客户端
-
-
解决
-
检查网络连接:
- 确认客户端和服务器之间的网络连接稳定,避免网络延迟过高。
-
检查
MySQL
服务器配置:- 查看并调整
MySQL
服务器的wait_timeout
和interactive_timeout
参数,确保它们设置合理。
- 查看并调整
-
检查防火墙配置:
- 确认防火墙规则允许客户端与服务器之间的通信。
-
调整连接池设置:
- 检查并调整连接池的配置参数
connection_pool_max_life_time
,确保小于MySQL
的wait_timeout
和interactive_timeout
参数并大于执行时间最长的SQL
- 检查并调整连接池的配置参数
-
监控服务器资源:
- 监控
MySQL
服务器的资源使用情况,确保有足够的资源处理连接请求。
- 监控
-
优化客户端配置:
- 确认
JDBC
驱动的配置参数正确,例如autoReconnect=true
,确保连接能在中断后自动重连。
- 确认
-
-
-
java.io.EOFException MESSAGE
:Can not read response from server. Expected to read 819 bytes, read 686 bytes before connection was unexpectedly lost.
-
原因:连接被
MySQL Kill
或者MySQL
宕机 -
解决:检查
MySQL
是否有主动kill
连接的机制,或者是否因为查询过大查崩MySQL
-
7 常见问题¶
-
读写
MySQL
的emoji
表情出现乱码Doris
进行MySQL Catalog
查询时,由于MySQL
之中默认的utf8
编码为utf8mb3
,无法表示需要4
字节编码的emoji
表情。这里需要将MySQL
的编码修改为utf8mb4
,以支持4
字节编码。可全局修改配置项
Bash 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
修改mysql目录下的my.ini文件(linux系统为etc目录下的my.cnf文件) [client] default-character-set=utf8mb4 [mysql] 设置mysql默认字符集 default-character-set=utf8mb4 [mysqld] 设置mysql字符集服务器 character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci init_connect='SET NAMES utf8mb4 修改对应表与列的类型 ALTER TABLE table_name MODIFY colum_name VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ALTER TABLE table_name CHARSET=utf8mb4; SET NAMES utf8mb4
-
读取
MySQL DATE/DATETIME
类型出现异常Bash 1 2 3
ERROR 1105 (HY000): errCode = 2, detailMessage = [10.16.10.6](INTERNAL_ERROR)UdfRuntimeException: get next block failed: CAUSED BY: SQLException: Zero date value prohibited CAUSED BY: DataReadException: Zero date value prohibited
这是因为
JDBC
中对于该非法的DATE/DATETIME
默认处理为抛出异常,可以通过参数zeroDateTimeBehavior
控制该行为。可选参数为:
exception
,convertToNull
,round
,分别为:异常报错,转为NULL
值,转为"0001-01-01 00:00:00"
;需要在创建
Catalog
的jdbc_url
把JDBC
连接串最后增加zeroDateTimeBehavior=convertToNull
,如"jdbc_url" = "jdbc:mysql://127.0.0.1:3306/test?zeroDateTimeBehavior=convertToNull"
这种情况下,JDBC
会把0000-00-00
或者0000-00-00 00:00:00
转换成null
,然后Doris
会把当前Catalog
的所有Date/DateTime
类型的列按照可空类型处理,这样就可以正常读取了。 -
读取
MySQL Catalog
或其他JDBC Catalog
时,出现加载类失败如以下异常:
Bash 1
failed to load driver class com.mysql.cj.jdbc.driver in either of hikariconfig class loader
这是因为在创建
Catalog
时,填写的driver_class
不正确,需要正确填写,如上方例子为大小写问题,应填写为"driver_class" = "com.mysql.cj.jdbc.Driver"
-
读取
MySQL
出现通信链路异常如果出现如下报错:
Bash 1 2 3 4 5 6 7
ERROR 1105 (HY000): errCode = 2, detailMessage = PoolInitializationException: Failed to initialize pool: Communications link failure The last packet successfully received from the server was 7 milliseconds ago. The last packet sent successfully to the server was 4 milliseconds ago. CAUSED BY: CommunicationsException: Communications link failure The last packet successfully received from the server was 7 milliseconds ago. The last packet sent successfully to the server was 4 milliseconds ago. CAUSED BY: SSLHandshakeExcepti
可查看
be
的be.out
日志如果包含以下信息:
Bash 1 2 3 4
WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
可在创建
Catalog
的jdbc_url
把JDBC
连接串最后增加?useSSL=false
,如"jdbc_url" = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false"
-
查询
MySQL
大数据量时,如果查询偶尔能够成功,偶尔会报如下错误,且出现该错误时MySQL
的连接被全部断开,无法连接到MySQL Server
,过段时间后MySQL
又恢复正常,但是之前的连接都没了:Bash 1 2 3
ERROR 1105 (HY000): errCode = 2, detailMessage = [INTERNAL_ERROR]UdfRuntimeException: JDBC executor sql has error: CAUSED BY: CommunicationsException: Communications link failure The last packet successfully received from the server was 4,446 milliseconds ago. The last packet sent successfully to the server was 4,446 milliseconds ago.
出现上述现象时,可能是
MySQL Server
自身的内存或CPU
资源被耗尽导致MySQL
服务不可用,可以尝试增大MySQL Server
的内存或CPU
配置。 -
查询
MySQL
的过程中,如果发现和在MySQL
库的查询结果不一致的情况首先要先排查下查询字段中是字符串否存在有大小写情况。比如,
Table
中有一个字段c_1
中有"aaa"
和"AAA"
两条数据,如果在初始化MySQL
数据库时未指定区分字符串大小写,那么MySQL
默认是不区分字符串大小写的,但是在Doris
中是严格区分大小写的,所以会出现以下情况:SQL 1 2 3 4 5
MySQL行为: select count(c_1) from table where c_1 = "aaa"; 未区分字符串大小,所以结果为:2 Doris行为: select count(c_1) from table where c_1 = "aaa"; 严格区分字符串大小,所以结果为:1
如果出现上述现象,那么需要按照需求来调整,方式如下:
在
MySQL
中查询时添加BINARY
关键字来强制区分大小写:select count(c_1) from table where BINARY c_1 = "aaa";
或者在
MySQL
中建表时候指定:CREATE TABLE table (c_1 VARCHAR(255) CHARACTER SET binary);
或者在初始化
MySQL
数据库时指定校对规则来区分大小写:Bash 1 2 3 4 5 6 7
[mysqld] character-set-server=utf8 collation-server=utf8_bin [client] default-character-set=utf8 [mysql] default-character-set=utf8
-
查询
MySQL
的时候,出现长时间卡住没有返回结果,或着卡住很长时间并且fe.warn.log
中出现出现大量write lock
日志,可以尝试在URL
添加socketTimeout
,例如:jdbc:mysql://host:port/database?socketTimeout=30000
,防止JDBC
客户端在被MySQL
关闭连接后无限等待。 -
在使用
MySQL Catalog
的过程中发现FE
的JVM
内存或Threads
数持续增长不减少,并可能同时出现Forward to master connection timed out
报错打印
FE
线程堆栈jstack fe_pid > fe.js
,如果出现大量mysql-cj-abandoned-connection-cleanup
线程,说明是MySQL JDBC
驱动的问题。按照如下方式处理:
-
升级
MySQL JDBC
驱动到8.0.31
及以上版本 -
在
FE
和BE conf
文件的JAVA_OPTS
中增加-Dcom.mysql.cj.disableAbandonedConnectionCleanup=true
参数,禁用MySQL JDBC
驱动的连接清理功能,并重启集群
注意:如果
Doris
的版本在2.0.13
及以上(2.0 Release
),或2.1.5
及以上(2.1 Release
)则无需增加该参数,因为Doris
已经默认禁用了MySQL JDBC
驱动的连接清理功能。只需更换MySQL JDBC
驱动版本即可。但是需要重启Doris
集群来清理掉之前的Threads
。 -