驱动与协议

共 19 题
📑 题目列表 19 题
#
★★★

1. JDBC 驱动类型,Type 1(JDBC-ODBC)、Type 2(Native)、Type 3(Net)、Type 4(Pure Java)?

JDBC 驱动的四种类型(Type 1 JDBC-ODBC、Type 2 Native、Type 3 Net、Type 4 Pure Java)分别是什么?各自优缺点?

  • 四种驱动类型的实现方式
  • 各自优缺点
  • 当前主流类型

JDBC 驱动分四种类型:Type 1(JDBC-ODBC 桥)通过 ODBC 桥接访问数据库,需要 ODBC 驱动,性能差、平台依赖,已基本废弃;Type 2(Native API)通过数据库厂商的本地库(native API)访问,性能好但需安装本地库、平台依赖;Type 3(Net)通过中间件服务器把 JDBC 调用转换为数据库协议,纯 Java 但需部署中间件;Type 4(Pure Java)纯 Java 直接实现数据库网络协议,无需本地库与中间件,性能好、跨平台,是当前主流(如 MySQL Connector/J、PostgreSQL pgjdbc 都是 Type 4)。

Type 4 驱动因纯 Java、跨平台、无需部署额外组件而成为主流。Type 1 已废弃,Type 2 平台依赖,Type 3 需中间件。

#
★★★

2. MySQL JDBC 驱动的 mysql-connector-j 与 prepareStatement 的优化?

MySQL JDBC 驱动 mysql-connector-j 与 prepareStatement 的优化是什么?

  • mysql-connector-j 的 prepareStatement 行为
  • 客户端 vs 服务端预编译
  • 相关参数(useServerPrepStmts、cachePrepStmts)

mysql-connector-j 默认使用客户端预编译(本地拼接参数),不真正使用服务端预编译;要启用服务端预编译需设置 useServerPrepStmts=true,通过 COM_STMT_PREPARE 在服务端预编译。配合 cachePrepStmts=true 可缓存预编译语句,避免重复 PREPARE。优化点:对频繁执行的 SQL 启用服务端预编译 + 缓存,可减少解析开销并防注入;但 MySQL 8 下服务端预编译有额外往返(PREPARE/EXECUTE),需权衡。批量插入再配合 rewriteBatchedStatements。

mysql-connector-j 的默认行为是客户端预编译,服务端预编译需显式开启。缓存预编译语句能减少重复 PREPARE 的网络往返。

#
★★★

3. PostgreSQL JDBC 驱动的 pgjdbc 与 PgBouncer 兼容模式?

PostgreSQL JDBC 驱动 pgjdbc 与 PgBouncer 兼容模式是什么?

  • pgjdbc 的预编译行为
  • PgBouncer 的池模式
  • 兼容配置

pgjdbc 默认关闭服务端预编译(使用扩展查询协议与无名语句,执行计划不被会话级缓存),通过 prepareThreshold 参数控制:当同一条 SQL 执行次数达到阈值后,驱动自动切换为服务端预编译(Parse/Bind/Execute)。PgBouncer 兼容方面:PgBouncer 的 transaction 池模式会释放连接,导致服务端预编译语句(prepared statement)在连接归还后失效,因此 pgjdbc 需配合 PgBouncer 的 prepared statement 支持(PgBouncer 的 server_prepared_statements 参数)或使用客户端预编译模式;PgBouncer 的 session 池模式则保留连接与预编译语句。兼容关键是理解池模式对 prepared statement 生命周期的影响。

prepareThreshold 决定是否切换服务端预编译;PgBouncer 的 transaction 池会破坏 prepared statement 状态,是兼容性的核心。

#
★★★

4. 连接串(Connection URL)的常见参数,useSSL、serverTimezone、characterEncoding?

数据库连接串(Connection URL)的常见参数 useSSL、serverTimezone、characterEncoding 分别是什么?

  • useSSL 加密连接
  • serverTimezone 时区
  • characterEncoding 字符集

useSSL 控制是否使用 SSL/TLS 加密连接(MySQL 8 默认启用 SSL,需配置 useSSL=true 或 useSSL=false 显式指定);serverTimezone 指定服务器时区(如 serverTimezone=Asia/Shanghai),避免驱动与服务器时区不一致导致日期时间错乱;characterEncoding 指定客户端字符集(如 characterEncoding=UTF-8),配合 useUnicode=true 保证多字节字符正确传输。这些参数不一致会导致:时区错误(日期偏移)、乱码(字符集不符)、连接失败(SSL 不匹配)。

连接串参数是"驱动与服务器之间的会话环境声明",必须与服务器端配置一致,否则出现隐性数据错误。

#
★★★

5. 数据库网络协议(PostgreSQL 前后端协议、MySQL 客户端/服务器协议)?

数据库网络协议是什么?PostgreSQL 前后端协议与 MySQL 客户端/服务器协议有什么特点?

  • 协议的分层与消息结构
  • PostgreSQL 前后端协议
  • MySQL 客户端/服务器协议

数据库网络协议是客户端与服务器之间交换消息的格式约定。PostgreSQL 前后端协议:客户端先发送 StartupMessage,进行认证(SCRAM-SHA-256),随后通过简单查询(Q)或扩展查询(Parse/Bind/Execute)发送 SQL,服务器返回 RowDescription、DataRow、CommandComplete 等消息,消息以字节长度前缀绑定。MySQL 客户端/服务器协议:客户端发送 COM_QUERY(文本协议)或 COM_STMT_PREPARE/EXECUTE(二进制协议),服务器返回 OK/ERR/ResultSet,文本协议结果以文本编码返回,二进制协议以二进制编码返回。两者都是基于 TCP 的请求-响应式协议,都有文本与二进制两种执行模式。

协议决定了 SQL 如何传输与结果如何编码。二进制协议编码紧凑、类型安全,效率更高;文本协议直观但传输开销大。

#
★★★

6. MySQL 8 caching_sha2_password 认证的完整流程(快速路径/完整路径)与 JDBC 兼容

MySQL 8 caching_sha2_password 认证的完整流程(快速路径/完整路径)是什么?JDBC 如何兼容?

  • caching_sha2_password 的原理
  • 快速路径(缓存命中)
  • 完整路径(RSA 交换)

caching_sha2_password 是 MySQL 8 默认认证插件。认证流程分两条路径:快速路径——服务器在其缓存中存有该用户的认证结果(SHA-256 哈希),客户端发送哈希后服务器直接比对,无需额外交换,速度快;完整路径——缓存未命中时,服务器要求客户端用 RSA 公钥加密密码后传输(或通过 TLS 明文传输),服务器解密验证并写入缓存。JDBC 兼容:mysql-connector-j 8+ 原生支持 caching_sha2_password,若连接为明文传输且未走 TLS,需配置 allowPublicKeyRetrieval=true 以允许客户端获取 RSA 公钥,或使用 SSL 连接。

caching_sha2_password 的快速/完整路径分别对应"缓存命中"与"缓存未命中"两种情况。完整路径依赖 RSA 或 TLS,JDBC 需 allowPublicKeyRetrieval 或 SSL 才能完成。

#
★★★

7. MySQL 的文本协议与预处理语句的二进制协议在结果集传输与类型安全上有何差异?为什么二进制协议更高效?

MySQL 文本协议与预处理语句的二进制协议在结果集传输与类型安全上有何差异?为什么二进制协议更高效?

  • 文本协议的结果集编码
  • 二进制协议的结果集编码
  • 类型安全差异

文本协议(COM_QUERY)下,结果集以文本字符串形式传输,每个字段都编码为字符串(如数字 123 变 "123"),驱动需解析字符串并转换回 Java 类型,无法保证类型安全,且传输体积大。二进制协议(COM_STMT_EXECUTE)下,结果集按各数据类型的原生二进制格式编码(如 INT 用 4 字节、DATE 用紧凑二进制),驱动直接按类型读取,无需字符串转换,类型安全、传输紧凑。因此二进制协议更高效:减少文本转换开销、传输体积更小、类型信息更精确。这就是预处理语句(二进制协议)在传输与类型安全上的优势。

二进制协议省去"文本→类型"的转换与更小的传输体积,是性能与类型安全的双重优势。也是服务端预编译被推荐的原因之一。

#
★★★

8. JDBC 如何实现查询取消?PostgreSQL 的 CancelRequest 与 MySQL 的 KILL QUERY 在协议层如何配合驱动超时?

JDBC 如何实现查询取消?PostgreSQL 的 CancelRequest 与 MySQL 的 KILL QUERY 在协议层如何配合驱动超时?

  • JDBC Statement.cancel
  • PostgreSQL CancelRequest
  • MySQL KILL QUERY

JDBC 通过 Statement.cancel() 取消查询。PostgreSQL 协议层使用 CancelRequest:客户端通过独立连接发送 CancelRequest(含 pid 与密钥),服务器终止对应查询。MySQL 则通过 KILL QUERY id 终止指定连接的当前查询。驱动超时(如 queryTimeout、socketTimeout)触发时,驱动会调用底层的取消机制——PostgreSQL 驱动发送 CancelRequest,MySQL 驱动发送 COM_QUERY KILL QUERY——向服务器发送终止请求,从而中断正在执行的 SQL。取消请求走独立/旁路连接,避免在阻塞的查询连接上发送。

查询取消是"客户端主动终止服务端查询"的机制,通过旁路连接(CancelRequest / KILL QUERY)实现,与驱动查询超时配合,使超时能真正中断服务端执行而不仅是客户端等待。

#
★★

9. MySQL caching_sha2_password 认证的快速路径与完整路径(RSA 交换)流程?JDBC 8+ 需要配置哪些参数才能兼容?

MySQL caching_sha2_password 认证的快速路径与完整路径(RSA 交换)流程是什么?JDBC 8+ 需要配置哪些参数?

  • 快速路径流程
  • 完整路径(RSA 交换)流程
  • JDBC 8+ 兼容参数

快速路径:服务器缓存中已存在该用户的认证结果,客户端发送 SHA-256 哈希,服务器比对成功即认证通过,无需额外交换。完整路径:缓存未命中,服务器发送认证挑战,客户端需用 RSA 公钥加密密码或通过 TLS 安全通道发送,服务器解密验证后缓存结果。JDBC 8+ 兼容:若未使用 TLS 且密码需要明文传输,需配置 allowPublicKeyRetrieval=true 让客户端获取 RSA 公钥;或使用 SSL 连接(useSSL=true)使密码经 TLS 传输而无需公钥检索。两者保证完整路径能完成认证。

快速路径依赖缓存,完整路径依赖 RSA 或 TLS。JDBC 在非 TLS 下需 allowPublicKeyRetrieval 才能走 RSA 完整路径,这是常见配置报错点。

#
★★

10. PgBouncer 的事务级与语句级池模式对 prepared statement、临时表与 LISTEN/NOTIFY 的影响?

PgBouncer 的事务级与语句级池模式对 prepared statement、临时表与 LISTEN/NOTIFY 有什么影响?

  • transaction 池模式的影响
  • statement 池模式的影响
  • prepared statement、临时表、LISTEN/NOTIFY 的会话状态

PgBouncer 的事务级(transaction)池模式在事务结束后立即归还连接给池,导致连接被其他客户端复用,会话级状态(prepared statement、临时表、LISTEN/NOTIFY)都会丢失或错乱:prepared statement 在连接归还后失效,临时表随连接复用而消失或被其他会话误用,LISTEN/NOTIFY 的订阅也会丢失。语句级(statement)池模式更严格,在每条语句后即归还连接,几乎不保留任何会话状态。因此这些会话状态相关功能在 transaction/statement 池模式下不可靠,需使用 session 池模式,或避免在池化连接中使用这些特性。

transaction/statement 池模式的核心是"连接复用",复用即破坏会话状态。prepared statement、临时表、LISTEN/NOTIFY 都是会话级状态,在复用模式下会失效,这是 PgBouncer 的已知限制。

#
★★

11. 数据库驱动连接参数(connectTimeout、socketTimeout)与数据库端 wait_timeout、interactive_timeout 如何配合,避免空闲连接被服务端提前断开?

数据库驱动连接参数(connectTimeout、socketTimeout)与数据库端 wait_timeout、interactive_timeout 如何配合?如何避免空闲连接被服务端提前断开?

  • connectTimeout 与 socketTimeout 的含义
  • 与 wait_timeout 的配合
  • 避免空闲连接被断开的策略

connectTimeout 是建立 TCP 连接的超时时间;socketTimeout 是单次读写(socket)的超时时间,即等待服务器响应的时间上限。数据库端 wait_timeout/interactive_timeout 是服务端断开空闲连接的阈值。配合上:socketTimeout 应设得足够大,避免慢查询被误杀,但也要防止无限等待;wait_timeout 决定服务端何时断开空闲连接。为"避免空闲连接被服务端提前断开",需让连接池保活周期 < wait_timeout,在服务端断开前通过心跳/验证查询激活连接;同时 connectTimeout 防止连接建立卡死,socketTimeout 防止单次请求无限挂起。三者配合形成"建立不超时、读写有限时、空闲有保活"的完整策略。

connectTimeout 管"建立",socketTimeout 管"读写",wait_timeout 管"服务端断开空闲"。保活周期小于 wait_timeout 是避免空闲连接被提前断开的关键。

#
★★

12. 数据库协议的身份认证流程,MySQL caching_sha2_password 与 PostgreSQL SCRAM-SHA-256 在握手消息交换上的差异?

数据库协议的身份认证流程中,MySQL caching_sha2_password 与 PostgreSQL SCRAM-SHA-256 在握手消息交换上有何差异?

  • caching_sha2_password 与 SCRAM-SHA-256 的认证流程
  • 握手消息交换的差异
  • 密码安全传输机制

MySQL caching_sha2_password:服务器发送认证插件与挑战,客户端做 SHA-256 哈希,快速路径下服务器比对缓存直接通过;完整路径下需 RSA 加密或 TLS 传输密码。PostgreSQL SCRAM-SHA-256:基于 RFC 5802,服务器发送 salt 与迭代次数,客户端计算 client-first-message,服务器返回 server-first-message(含 salt),客户端计算 client-final-message(含 proof),服务器验证 proof 并返回 server-final-message 确认。差异:SCRAM 是标准的挑战-响应(challenge-response)协议,密码永不直接传输(客户端证明知道密码),支持服务器端证明;caching_sha2_password 是非标准的快速哈希 + 可选 RSA/TLS 明文密码传输。两者在消息交换流程、密码传输方式与安全性设计上不同。

SCRAM 通过"证明知道密码"而非"传输密码"实现认证,且支持双向验证;caching_sha2_password 用哈希缓存提升速度,完整路径依赖 RSA/TLS。这是两种协议握手的本质差异。

#
★★

13. MySQL 驱动的 rewriteBatchedStatements 与 useServerPrepStmts 组合对批量 INSERT 的网络往返与解析开销有何影响?

MySQL 驱动的 rewriteBatchedStatements 与 useServerPrepStmts 组合对批量 INSERT 的网络往返与解析开销有什么影响?

  • rewriteBatchedStatements 与 useServerPrepStmts 的交互
  • 网络往返与解析开销
  • 组合效果

rewriteBatchedStatements 将批量 INSERT 重写为多值 INSERT,减少网络往返;useServerPrepStmts 启用服务端预编译,减少解析开销。两者组合时:rewriteBatchedStatements 生效时,驱动通常把多条 INSERT 合并为文本的多值 SQL 发送,此时 useServerPrepStmts 的服务端预编译可能不适用于重写后的多值语句(或需要特殊处理),因为重写改变 SQL 文本。组合效果是:网络往返大幅减少(多值合并),但解析开销取决于是否走服务端预编译——重写后的多值语句若走服务端预编译需额外 PREPARE,若走文本协议则解析由服务端完成但在某些场景下服务端预编译参数化不生效。实践中 rewriteBatchedStatements 对批量 INSERT 的收益大,是否叠加 useServerPrepStmts 需权衡。

rewriteBatchedStatements 优化"往返",useServerPrepStmts 优化"解析"。两者组合时重写会改变语句形态,可能影响服务端预编译的复用,需按实际场景测试收益。

#
★★

14. PostgreSQL 扩展查询协议(Parse/Bind/Execute)与预编译语句的对应关系

PostgreSQL 扩展查询协议(Parse/Bind/Execute)与预编译语句的对应关系是什么?

  • Parse/Bind/Execute 三个阶段
  • 与预编译语句的对应
  • 服务端预编译的生命周期

PostgreSQL 扩展查询协议分三个阶段:Parse——解析 SQL 文本并生成服务端预编译语句(prepared statement),可命名并缓存;Bind——将参数绑定到预编译语句,生成执行计划(portal);Execute——执行并返回结果。这与 JDBC 的 PreparedStatement 对应:prepareStatement 触发 Parse,setXxx 后执行触发 Bind+Execute。通过 PREPARE 语句可显式命名预编译语句,多次 EXECUTE 复用同一 Parse 结果,减少解析开销。这是 pgjdbc 在 prepareThreshold 达到后自动切换的协议基础。

扩展查询协议把"解析"与"执行"分离,Parse 一次、Bind/Execute 多次,从而复用预编译语句与执行计划。这是服务端预编译的协议支撑。

#
★★

15. JDBC 的 setFetchSize 与游标模式(useCursorFetch)如何避免大结果集 OOM?与数据库端游标资源释放的关系是什么?

JDBC 的 setFetchSize 与游标模式(useCursorFetch)如何避免大结果集 OOM?与数据库端游标资源释放的关系是什么?

  • setFetchSize 分批拉取
  • useCursorFetch 游标模式
  • 数据库端游标资源释放

默认非游标模式下,驱动一次性拉取全部结果集到内存,大结果集 OOM。setFetchSize(n) 设置每次从数据库取回的行数,配合 useCursorFetch=true(MySQL)启用服务端游标,驱动按 fetchSize 分批拉取,内存只保留当前批次,避免 OOM。数据库端游标会在结果集遍历完或连接关闭时释放;若未遍历完就关闭连接,游标资源也随之释放(连接关闭隐含释放游标)。因此游标模式必须保持连接开启、遍历完结果集并关闭 Statement/ResultSet,否则游标长期占用数据库资源。PostgreSQL 驱动用 setFetchSize 也能触发游标行为。

游标模式的核心是"分批拉取 + 服务端游标"。内存安全靠分批,但游标资源需通过完成遍历/关闭来释放,这是资源管理的关键。

#

16. 驱动连接参数,useSSL、verifyServerCertificate 与服务器 TLS 配置的配合,以及 profileSQL/logSlowQueries 日志开关的用途?

驱动连接参数 useSSL、verifyServerCertificate 与服务器 TLS 配置如何配合?profileSQL/logSlowQueries 日志开关的用途是什么?

  • useSSL 与 verifyServerCertificate
  • 服务器 TLS 配置
  • profileSQL/logSlowQueries 日志

useSSL 控制是否启用 SSL 加密连接;verifyServerCertificate 控制是否验证服务器证书(需配合 trustStore 提供信任的 CA)。要完整验证服务器,需 useSSL=true + verifyServerCertificate=true + 配置 trustStore,保证客户端信任并验证服务器证书,防止中间人攻击;若只想加密不验证证书,可 verifyServerCertificate=false。这需与服务器 TLS 配置(证书、CA、SSL 启用)配合。profileSQL 驱动日志开关会记录驱动发送的 SQL 与参数,用于调试;logSlowQueries 记录超过 slowQueryThresholdMillis 的慢查询,用于性能诊断。两者都是排查 SQL 与性能问题的诊断工具。

verifyServerCertificate 决定是否验证服务器身份,是 SSL 安全性的完整保障;profileSQL/logSlowQueries 是驱动级诊断日志,帮助定位 SQL 与性能问题。

#

17. 连接池与驱动的配合,getConnection 的超时与校验?

连接池与驱动如何配合?getConnection 的超时与校验是什么?

  • getConnection 超时
  • 连接校验
  • 连接池与驱动的超时层次

连接池的 getConnection 超时(Druid 的 maxWait、HikariCP 的 connectionTimeout)控制从池中获取连接的最长等待时间,超过则抛异常,避免请求无限等待。驱动层 ConnectTimeout 控制建立实际 TCP 连接的超时。两者配合:池内有连接时快速返回,池空时等待直到 maxWait 超时或新建连接(新建连接的耗时受驱动 ConnectTimeout 约束)。校验:getConnection 时池可能做 test-on-borrow 校验(执行验证查询)确保返回的连接有效,校验失败则剔除并重建。整体形成"池等待超时 + 驱动建连超时 + 连接有效性校验"的多层保护。

连接池超时管"池内等待",驱动超时管"底层建连",校验管"连接有效性"。三层配合保证获取连接稳定、受限、有效。

#

18. 驱动连接串的故障转移参数(loadBalance/failover)与只读路由(readOnly)

驱动连接串的故障转移参数(loadBalance/failover)与只读路由(readOnly)是什么?

  • 故障转移参数(loadBalance/failover)
  • 只读路由(readOnly)
  • 高可用与读写分离

部分驱动(如 MySQL Connector/J 的如 failover、loadBalance 参数)支持在连接串中配置多个主机实现故障转移与负载均衡:failover 在主机不可用时切换备用主机,loadBalance 在多个主机间分配负载(如 random、round-robin)。readOnly 参数(Connection.setReadOnly(true) 或 URL 参数)标记连接为只读,驱动/连接池可据此把查询路由到只读从库,实现读写分离。这些参数配合高可用组件与读写分离中间件,实现连接层的高可用与读流量分流。注意:failover 的故障切换可能不保证事务一致性,需配合连接池重连。

故障转移参数提供"连接级高可用",readOnly 提供"读写分离路由"。两者都是驱动层对高可用与读扩展的支撑,但 failover 切换有事务丢失风险。

#

19. JDBC DatabaseMetaData 的元数据查询会访问 information_schema,为什么高并发初始化场景下会成为性能瓶颈?如何缓存?

JDBC DatabaseMetaData 的元数据查询会访问 information_schema,为什么高并发初始化场景下会成为性能瓶颈?如何缓存?

  • DatabaseMetaData 与 information_schema
  • 高并发初始化的瓶颈
  • 缓存策略

DatabaseMetaData 的元数据查询(如获取表结构、列信息)通常访问 information_schema(MySQL)或系统目录(PostgreSQL),这些查询需要扫描系统元数据表,开销较大。在高并发初始化场景(如大量应用实例同时启动、频繁获取元数据)下,大量并发的元数据查询会集中在 information_schema 上,造成锁竞争与查询瓶颈,甚至影响数据库整体性能。缓存策略:只在应用启动时查询一次元数据并缓存到内存(如 ORM 的表结构映射、连接池的元数据缓存),避免每个连接/每次请求重复查询;通过连接池/ORM 的元数据缓存(如 Hibernate 的命名策略缓存、MyBatis 的 Statement 缓存)减少重复访问;必要时用静态配置替代运行时元数据查询。

information_schema 是集中式系统表,并发扫描成本高。缓存"启动时查一次、运行期复用"是避免瓶颈的关键。