一、关系数据源连接基本原理

Smartbi的主服务、OLAP、ETL通过JDBC驱动给数据库服务器发送SQL或者JDBC指令,数据库服务器接收请求后分配资源执行作业并在作业结束后将结果回传给驱动,最后BI调用驱动接口获取结果,执行BI的业务逻辑。整个访问链路的核心是JDBC驱动,它是BI和数据库服务器沟通的桥梁。

二、JDBC驱动介绍

JDBC驱动是Java应用与数据库之间的「翻译器」,负责将Java代码中的SQL请求转换为数据库能理解的语言,并把结果返回给Java程序。BI、OLAP、ETL都是Java应用,对数据库的操作依赖于JDBC驱动。市面上有各种各样的数据库,它们提供的JDBC驱动不尽相同。以获取数据库连接为例,如果每种驱动获取连接的接口都是独特,那BI需要针对不同数据库实现不同的代码逻辑,这将是灾难性的。幸运的是,Java社区很早就考虑到了。Java社区发布了一套JDBC规范,各数据库厂商按照JDBC规范实现各自的驱动,Java应用只需要按照JDBC规范调用驱动接口,只需要一套代码,即可与不同数据库1232px无缝交互。由此可见,BI能否对应某个新型数据库,取决于该数据库能否提供标准的JDBC驱动。

2.1JDBC驱动关键概念

驱动类,也就是Driver类,是数据库JDBC驱动对外的入口。驱动类接收应用传入的连接字符串和连接参数,之后通过网络协议与数据库建立会话连接,以便执行后续的数据库操作。不同数据库驱动有各种不同驱动类,比如MYSQL的驱动类是:com.mysql.jdbc.Driver。数据源测试连接的第一个步骤就是从驱动jar中加载驱动类。

连接字符串URL是Java应用程序连接数据库的关键配置之一,用于指定数据库的类型、位置、端口、名称以及其他连接参数。

JDBC连接字符串URL的通用结构是:

jdbc:<子协议>:<子名称>://<主机名>:<端口>/<数据库名>[?<参数>=<值>...]

协议:固定为 jdbc:,表示Java数据库连接。
子协议:指定数据库类型(如 mysql, oracle, postgresql 等)。
子名称:某些数据库需要额外参数(如 thin 是Oracle的驱动类型)。
主机名:数据库服务器的IP地址或主机名(如 localhost)。
端口:数据库服务的端口号(如MySQL默认3306,PostgreSQL默认5432)。
数据库名:要连接的数据库名称。
参数:可选的连接参数(如SSL配置、时区等),第一个参数前用?分隔,后接多个参数时用&连接。有些数据库如MS SQL Server比较特殊,不使用用?和&,统一使用分号;分隔。


数据库

驱动类

连接字符串示例

MySQL

com.mysql.jdbc.Driver

jdbc:mysql://localhost:3306/mydb?useSSL=false&characterEncoding=UTF-8&autoReconnect=true

MySQL 8+

com.mysql.cj.jdbc.Driver

jdbc:mysql://localhost:3306/mydb?useSSL=false&characterEncoding=UTF-8&autoReconnect=true

PostgreSQL

org.postgresql.Driver

jdbc:postgresql://localhost:5432/mydb?user=myuser&password=mypass&connectTimeout=10000

SQL Server

net.sourceforge.jtds.jdbc.Driver

jdbc:jtds:sqlserver://<servername>:1433;DatabaseName=<database>

Oracle

oracle.jdbc.driver.OracleDriver

jdbc:oracle:thin:@//localhost:1521/orcl?user=myuser&password=mypass

MariaDB

org.mariadb.jdbc.Driver

jdbc:mariadb://localhost:3306/mydb?user=myuser&password=mypass&useUnicode=true&characterEncoding=utf8mb4

2.2创建连接过程

数据库连接是指应用程序与数据库服务器之间建立的一条通信通道,通过这条通道,应用程序可以向数据库发送查询、插入、更新、删除等操作请求,并获取数据库返回的结果。它是实现应用程序与数据库交互的基础。

下图介绍了创建数据库连接的过程,开始阶段可以看作在数据源界面点击测试连接,看看BI是怎么一步步进行的。

1)加载驱动

数据源配置界面有两个与加载驱动过程密切相关的配置:驱动路径(产品内置、自定义)和驱动类。加载驱动的过程其实就是从驱动路径上找到驱动类,为后续创建连接做准备。

有两个关键因素影响加载驱动能否成功:

2)创建连接

创建连接的过程很简单,就是给驱动类接口传入连接字符串和认证信息,之后接口返回创建好的数据库连接。其对应一句代码:

// driver即驱动类, url即连接字符串,properties即连接参数,包含认证用户信息
Connection conn = driver.connect(url, properties);

虽然创建连接的逻辑很简单,但我们遇到的问题往往主要集中在这里。主要有以下四个问题点:

三、常见问题分类

大部分数据源连不上问题都发生在加载驱动创建连接两个阶段,接下来说明两个阶段会有哪些典型问题。

3.1加载驱动

加载驱动阶段包含以下主要问题:

1)驱动目录下不存在驱动类

以连接行云数据库为例,测试连接抛出异常“连接池初始化失败: 数据库驱动找不到com.bonc.xcloud.jdbc.XCloudDriver”,报错信息说找不到驱动了。首先我们确认驱动类配置得对不对,发现配置的驱动类“com.bonc.xcloud.jdbc.XCloudDriver”是正确的。那接下来确认驱动目录下有没有这个类,可以使用BI的类查找功能。

注意到数据源配置了自定义驱动目录,产品将会在sybase目录加载行云的驱动类。在系统监控/类查找中发现对应的驱动类不存在,那我们考虑驱动目录选错了,或者放入的jar不全。

调整驱动目录后,测试连接正常了,并且附上类查找效果图。

2)驱动包不全或者有jar包冲突问题

常见于一些大数据相关库,它们的驱动包通常不止一个,少一个或者多一个jar都有可能导致程序无法正常加载驱动。驱动包不全容易理解,就是缺少了某个jar,将jar包补上即可。jar包冲突比较复杂,有可能驱动目录下有两个不同版本的jar,也有可能驱动的类包与产品自带的类包冲突了。通常的报错有ClassNotFoundException或者NoClassDefineFound。这种报错解决方法不好归纳,需要根据系统日志综合判断。

3.2创建连接

创建连接阶段包含以下主要问题:

1)连接字符串不合规范,或者无法匹配当前驱动版本和数据库版本

比如mysql驱动_JDBC_mysql-connector-java-5.1.48在JDK9及以上版本时,需要加连接参数useSSL=false,否则会连不上。

如上图,mysql测试连接失败,我们从栈信息中提取到这样的报错,从报错关键字ssl可以知道跟加密连接有关,结合网上查询到的线索,可以配置useSSL=false规避。

Caused by: javax.net.ssl.SSLException: Received fatal alert: internal_error
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:208) ~[?:1.8.0_202]
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:154) ~[?:1.8.0_202]
    at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2020) ~[?:1.8.0_202]
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1127) ~[?:1.8.0_202]
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367) ~[?:1.8.0_202]
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395) ~[?:1.8.0_202]
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379) ~[?:1.8.0_202]
    at com.mysql.jdbc.ExportControlled.transformSocketToSSLSocket(ExportControlled.java:186) ~[_JDBC_mysql-connector-java-5.1.48.jar:5.1.48]

2)网络问题

网络不可达或者网络拦截导致BI到数据库服务器的网络不通,下面罗列一些常见的网络原因报错。网络问题可以通过telnet、ssh等工具测试网络是否通畅,但从排查角度上来说,很多网络问题都需要跟客户网络运维一起排查。

报错关键字

网络错误分类

可能原因

java.net.ConnectException: Connection refused

连接超时类错误

  1. 目标服务器未启动或未在指定端口监听。

  2. 服务器地址或端口号错误。

  3. 防火墙阻止了连接请求

java.net.SocketTimeoutException: Connect timed out

连接超时类错误

  1. 网络连接不稳定或延迟过高。

  2. 目标服务器繁忙,无法响应连接请求。

  3. 中间网络设备(如路由器)故障。

java.net.UnknownHostException

DNS 解析失败

  1. 域名拼写错误(如 htps://google.com)。

  2. DNS 服务器配置错误或不可用。

  3. 域名不存在或已过期。

java.net.SocketException: Connection reset

连接中断或丢失

  1. 服务器主动关闭连接(如超时、资源不足)。

  2. 网络中断导致数据包丢失。

java.net.SocketException: Broken pipe

连接中断或丢失

  1. 向已关闭的连接写入数据。

  2. 服务器在客户端发送数据时关闭了连接。

3)数据库服务器认证失败或者鉴权失败

常见的一些错误信息:

数据库类型

错误信息

核心原因

解决方案

MySQL

Access denied for user 'user'@'host' (using password: YES)

用户名或密码错误(区分大小写)

1. 检查用户名、密码是否正确
2. 确保数据库服务已启动并允许远程连接(如bind-address配置)

MySQL

Access denied for user 'user'@'host' (using password: NO)

连接时未提供密码,但数据库要求认证

在连接字符串或参数中提供正确的密码

MySQL

Access denied for user 'user'@'host' to database 'dbname'

用户无目标数据库的访问权限

执行 GRANT ALL PRIVILEGES ON dbname.* TO 'user'@'host'; 并刷新权限

MySQL

Host 'client_ip' is not allowed to connect

用户的host字段限制了访问来源(如仅允许localhost

修改用户权限:CREATE USER 'user'@'%' IDENTIFIED BY 'pwd';%表示允许所有IP)

PostgreSQL

FATAL: password authentication failed for user "user"

密码错误或驱动不兼容认证方式(如旧驱动不支持scram-sha-256

1. 检查密码正确性
2. 确保驱动版本支持SCRAM认证(如PostgreSQL 10+需驱动42.2+)

PostgreSQL

FATAL: role "user" does not exist

用户角色未在数据库中创建

执行 CREATE ROLE unknown_user WITH LOGIN PASSWORD 'pwd';

PostgreSQL

permission denied to create database

用户无CREATEDB权限

执行 ALTER ROLE user CREATEDB;

Oracle

ORA-01017: invalid username/password; logon denied

用户名或密码错误(区分大小写)

1. 确保用户名和密码大小写正确(Oracle默认大写)
2. 检查TNS连接配置

Oracle

ORA-01031: insufficient privileges

用户无目标操作权限(如CREATE SESSION

执行 GRANT CREATE SESSION TO user;

SQL Server

Login failed for user 'user'

用户名/密码错误或未启用混合认证模式

1. 检查密码
2. 确保SQL Server配置为混合认证模式(Windows认证+SQL Server认证)

SQL Server

The server principal "user" cannot access the database "dbname"

用户未被映射到目标数据库

执行 USE dbname; CREATE USER user FROM LOGIN user;

四、定位排查问题

通过以上说明,我们对于基本原理和常见的错误类型已经有了基本的概念,接下来我们可以通过以下步骤,定位数据库连接失败的根本原因,并针对性进行解决。

步骤1:确认其他JDBC工具有没有成功连上的先例。

这个步骤其实很关键,可以过滤很多非BI因素的问题。如果有其他JDBC工具(如)可以成功连上,那可以确认驱动类、驱动包、连接字符串、账号密码是否有差异。如果有差异,保证数据源的所有配置信息都与第三方工具保持一致。如果其他JDBC工具也无法正常连接,那得考虑数据库和网络等第三方原因。

步骤2:查看报错信息与日志。

参考【如何处理功能报错类异常】,获取详细的报错堆栈日志或者导出Smartbi系统日志,一般是找到报错堆栈最后一个Caused by:后的内容,通常为问题根源。

下图的报错信息可看的内容不多,为了进一步确定问题,可以拿一下完整的栈信息,我们定位到最后哦一个Caused by,才发现问题所在。

步骤3:基于报错关键字进行分析。

阅读Caused by:后的错误内容,看是否能够对应到上述说的哪一类问题,并进行解决。若无法自行定位,可使用AI辅助进行诊断,将错误描述或代码输入AI工具,尝试AI定位的问题类型和解决方案进行解决。也可将错误代码复制至WIKI等企业内部资源进行检索。注意:每个数据库的报错可能不同,例如,MySQL、Oracle、SQL Server在相同问题下可能会有不同的报错信息,这里不一一进行说明。以useSSL=false的实例,参考AI的回答,在第一个回答中已经提示禁用useSSL=false。

步骤4:通过第三方工具测试。

很多情况下网络或者数据库的特殊配置会导致数据源连不上,这时候需要客户的网络运维或者DBA参与解决,往往需要我们给出佐证,这时候可以在BI服务器上通过第三方工具进行测试,如果问题原因不在BI端,需要客户协调数据库或者网络运维资源,我们从旁协助。

1)网络测试工具

常见的网络测试命令有ping、telnet。ping命令测试主机间的网络连通性,测不了端口。telnet命令测端口连通性,但很多Window或Linux默认没有启用或安装。这里介绍另外一种SSH测试的方法,Windows和Linux环境一般都有默认安装。更多测试方法参考FAQ文档:如何检测系统间的网络通讯是否正常 - FAQ中心 -

SSH命令格式:ssh IP地址 -p 端口号 -v

比如我们测试wiki服务器的地址:ssh wiki.smartbi.com.cn -p 8443 -v,如果成功,则有 Connection established相关提示,如果失败则有Connection refused相关提示。

成功的示例:

网络不通的示例:

不会提示 Connection established,首先是长时间的连接过程,输出Connecting to xxx的日志

最后会输出连接超时的报错。

2)JDBC查询工具

JDBC查询工具是基于JDBC逻辑的,抛开具体的BI逻辑,可进行测试连接、对比执行结果、耗时长短等。常用测试工具有:DBeaver工具jsp测试工具jar测试工具

工具

说明

特点/不足

Dbeaver

DBeaver 是一款免费、开源的通用数据库管理工具,支持几乎所有主流数据库

特点:脱离BI应用验证;

不足:服务器上一般没有预装Dbeaver,无法直接验证

JSP测试工具

一些JSP测试页面,可以测试JDBC查询、获取表信息等操作

特点:代码可见,基于驱动逻辑,代码即改即生效;

不足:需要依赖BI,不能在OLAP或者ETL等组件服务器上单独测试

Jar测试工具

通过java代码写的java类或者jar包测试工具

特点:代码可见,即时编译执行,只要有jdk,就可以在BI、OLAP、ETL等各组件服务器上运行;支持模拟多线程并发查询;

不足:界面展示没那么直观

步骤5:提JIRA寻求帮助。

通过前期的排查仍然定位不到问题的,可以提JIRA寻求技术支持的帮助。JIRA中需要包含BI版本信息、报错详细日志、前期排查的一些结果等,避免反馈信息量少的截图。如果客户无法发回日志文件,至少把报错弹窗的完整栈信息拍照发回。如:下图,最开始只是弹窗提示说“连接池初始化失败”,如果将其作为日志反馈,是一个无效的日志。点击【显示栈信息】之后,找到最后一个Caused by文本位置,才能发现有用的信息。