JDBC

来自 PostgreSQL 维基
跳转到导航跳转到搜索

JDBC 是 Java 1.1 及更高版本的核心 API。它提供了一套标准的接口来访问符合 SQL 标准的数据库。

PostgreSQL 提供了一个类型 4 JDBC 驱动程序。类型 4 表示驱动程序是用纯 Java 编写的,并使用数据库系统的原生网络协议进行通信。因此,驱动程序是平台无关的;编译后,驱动程序可以在任何系统上使用。

用户文档

开发项目

当前状态

驱动程序是在几年前编写的(在 NIO 之前),现在开始显露出它的年代感。

在加密连接中,确定是否有更多数据的方法是进行阻塞读取,这存在一个问题。

我们希望避免阻塞 I/O。一个解决方案是引入一个监控线程,监控所有连接的事件。这感觉很像重新发明 NIO。另一个解决方案是使用 NIO 重新编写驱动程序。考虑到 NIO 的成熟度,我认为这是理想的方向。

也就是说,我认为由于 Netty 抽象了一些 NIO 的复杂性,使用 Netty 重新编写驱动程序是有意义的。

aht 提出的驱动程序新架构建议

首先,我绝对赞成使用 Netty。Netty 是一个非常成熟、健壮、高效且经过实战考验的网络 I/O 框架。它从驱动程序中减轻了大量的负担,同时提供了一个更简单的编程模型,几乎抽象了 socket 的世界,可以使用堆外缓冲区,并且在高性能环境(阅读:Twitter)中被广泛使用。+1 给 Netty。

我想建议以非常模块化的方式构建该层,尝试将其拆分成模块,以便这些模块中的大多数(如果不是全部)可以独立地被第三方使用。这不仅明显有利于驱动程序更简洁的设计和分离关注点,而且拓宽了代码用户的范围,这将有助于提高代码的质量和正确性。例如,协议层(消息格式、编码器、解码器等)可以被其他驱动程序使用,从而有效地实现了 Java 的“代码重用”目标。

无论这些模块是在 pgjdbc 中的单独仓库还是单独的 Maven 工件,我都建议使用以下模块

  • "FEBE" 模块
    • common: 包含 Fe/Be 协议中所有消息的定义(即 POJO 或等效项)。它不对消息的发送/接收或使用方式做任何假设,只包含它们的定义。封装了关于它们的字节结构的知识。
    • client: 包含用于对 FeBe 客户端(如驱动程序)发送的消息进行编码的编码器和用于对服务器发送的消息进行解码的解码器。它依赖于 "common"。
    • server: 包含用于对假设的 Java PostgreSQL 服务器发送的消息进行编码的编码器和用于对客户端发送的消息进行解码的解码器。虽然此模块是可选的,但它可以服务于两种目的:一是用于驱动程序的集成测试,创建基于 Java 的简单“模拟”PostgreSQL 服务器;二是作为创建服务器端 PostgreSQL 服务器(例如模拟服务器,甚至代理/连接池)的基础。它依赖于 "common"。
  • netty-client: 建立在 "common" 和 "client" 之上的模块,使用 Netty 发送/接收消息。它是驱动程序无关的,也就是说,你可以在此基础上构建一个 JDBC 或完全异步的驱动程序。它提供具有回调/IoC 的接口,以便插入驱动程序的功能。
  • pgjdbc: 建立在 netty-client 之上,实现 JDBC 标准。这是现有代码的重要部分将被移植的地方。
  • 可选模块。其他包含辅助功能的模块也可以与驱动程序分开开发,并且可以成为其他项目的基石。
    • 例如,当前驱动程序包含一个基本的“SQL 解析器”。然而,一个完整的 Java SQL 解析器(可能使用 Antlr 实现)对于驱动程序和其他独立项目来说都非常有用。
    • SCRAM。已经是外部依赖项 (https://github.com/ongres/scram).
    • CDC(变更数据捕获)抽象层建立在当前驱动程序之上,抽象了逻辑解码插件的使用。可以被其他软件重复使用,例如 Debezium.

这种架构并非理论上的。我在一个项目中采用了非常类似的方法,但这个项目在不久之后就成了废弃软件(时间限制)。但是,它至少反映了这些原则,至少对于 FEBE 部分而言。请查看 Phoebe。如果可以帮助,从该项目中拯救部分代码并将其作为该新架构的基础,不会有任何问题。这种实现没有完全遵循上述架构,因为 FEBE 模块依赖于 netty-buffer。但这实际上不是 Netty 本身,而只是一种方便的方式来表示可以被切片的字节数组。但是,如果需要,这可以进一步抽象出来。除此之外,该项目可能还有一些有用的部分可以使用,例如 MessageType,这是一个枚举,它编码了 FEBE 协议中每条消息的所有属性,并作为每条消息实现的基础。如果可以帮助,phoebe 的任何代码都可以 100% 捐赠给 pgjdbc。

特性 / 目标

  • 对结果进行逐行处理,无需设置事务或获取大小。这不必暴露给 JDBC 层,但核心驱动程序应该允许指定类似于接口或回调的东西,用于逐行结果处理。
  • 允许任意 PostgreSQL 命令,而不必预先知道结果类型是标准结果集响应还是 CopyOut 响应。这对于 CopyIn 可能不是必需的,因为用户需要提供数据,因此预先知道命令类型。