【问题标题】:Why are prepared statements kept at a connection level by the JDBC drivers?为什么 JDBC 驱动程序将准备好的语句保持在连接级别?
【发布时间】:2015-07-14 02:27:17
【问题描述】:

我并不是要问他们究竟做了什么,而是要问他们为什么要以现在的方式实施。如果准备好的语句完全由数据库处理,它不是对所有连接都可用吗?但似乎大部分都是由驱动程序针对连接处理的,我无法理解其背后的原因。

询问 Postgres。

【问题讨论】:

    标签: java mysql postgresql jdbc prepared-statement


    【解决方案1】:

    如果准备好语句,则将其发送到数据库,数据库解析和分析该语句并返回某种句柄 (=id),以后可以根据需要经常使用该句柄来执行该语句。因此,与其一遍又一遍地将整个语句发送到数据库,不如只将句柄和可能的查询参数传输到数据库。

    正如您已经发现的那样,prepared statements 绑定到当前数据库连接,因此当连接关闭时,该语句将从数据库缓存中删除。

    我不知道你认为将这些准备好的陈述公开给所有联系会有什么好处。如果您确实希望将公共语句存储在服务器上,请改用stored proceduresSQL views

    【讨论】:

    • 哦,我不知道返回的句柄部分。我在想,如果它正在发送一些哈希/完整的 sql 查询,那么无论它来自哪个连接,都可以跳过查询编译/规划部分。想法?
    • 好的,这就是您的想法。某种优化缓存,以防另一个连接之前已经发送过相同的语句。我不知道数据库(如 Postgres)是否已经(在内部)这样做了,但是你可以用准备好的语句来控制它。不同的故事。
    • 据我了解,有些jdbc连接池可以对prepared statements进行高级处理。您从池中获得的连接与原始 jdbc 连接没有直接关系。他们可以将已经准备好的语句定向到缓存的连接等。
    • 次要点:postgres 从不发回某种句柄。客户端发送PREPARE name-of-statement AS query-for-statement 或协议级别的等价物,PostgreSQL 回复成功或错误。提出连接中唯一名称的责任在客户端。
    【解决方案2】:

    prepared statement 绑定到连接有几个原因(从 JDBC 从数据库的角度来看),它们归结为“简单”:

    1. 资源管理:通过将语句与连接相关联,很容易清理任何尚未显式关闭的语句:如果连接关闭,任何打开的语句也将关闭。

    2. 在大多数数据库系统中,语句句柄也是游标句柄,这意味着它一次只能由一个连接使用,将其绑定到一个连接会更有意义。

    3. 语句生命周期(或至少执行生命周期,参见 2)与事务相关联,事务也绑定到连接。一些数据库允许一个连接上有多个活动事务,但 JDBC 假定每个连接一个。

    4. 在大多数数据库系统中,语句的准备取决于准备它的事务的元数据 (DDL) 可见性,拥有全局池会使这变得复杂(例如,允许使用哪个连接/查看哪个语句)。

    5. 有时在准备时会部分检查用户权限和特权。全局池会使这复杂化(参见 4)。

    我现在可能忘记了其他一些原因。我认为最重要的是第一个(如果有全局池,其他的实现方式会有所不同)。

    这并不会阻止数据库系统也拥有一个全局准备好的语句池(或至少:准备元数据,如访问路径、执行计划等)。然而,从用户的角度来看,一个准备好的语句的实例仍然绑定到一个连接。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-03
      • 2013-07-10
      • 1970-01-01
      • 2018-03-14
      • 2015-07-12
      • 2011-07-09
      • 2014-04-25
      相关资源
      最近更新 更多