【问题标题】:What's the difference between cachePrepStmts and useServerPrepStmts in MySQL JDBC DriverMySQL JDBC Driver中cachePrepStmts和useServerPrepStmts有什么区别
【发布时间】:2015-11-24 00:40:50
【问题描述】:

MySQL JDBC 驱动程序将这两个属性定义为:

  • useServerPrepStmts - 如果服务器支持,使用服务器端准备好的语句?

  • cachePrepStmts - 如果驱动程序缓存客户端准备语句的 PreparedStatements 的解析阶段,则“检查” 服务器端准备和服务器端准备的适用性 声明本身?

客户端预处理语句是重用PreparedStatements 对象的一种方式吗?

如果启用了useServerPrepStmts,究竟缓存了什么,因为 MySQL 没有execution plan cache anyway

【问题讨论】:

    标签: mysql database caching jdbc prepared-statement


    【解决方案1】:

    首先,区分客户端和服务器准备语句很重要。

    客户准备报表

    客户端准备好的语句是“模拟的”准备好的语句。这意味着 SQL 语句字符串在客户端被标记化,并且在将语句发送到服务器执行之前,所有占位符都被替换为文字值。每次执行时,都会将完整的 SQL 语句发送到服务器。您可以使用常规日志来调查其工作原理。例如

    以下代码:

    ps=conn.prepareStatement("select ?")
    ps.setInt(1, 42)
    ps.executeQuery()
    ps.setInt(1, 43)
    ps.executeQuery()
    

    会在日志中显示:

    255 Query  select 42
    255 Query  select 43
    

    “查询”表示,在协议级别,发送COM_QUERY 命令,后面有语句字符串。

    服务器准备语句

    服务器准备好的语句是“真正的”准备好的语句,这意味着查询文本被发送到服务器,被解析,占位符和结果信息被返回给客户端。这是设置useServerPrepStmts=true 时得到的结果。语句字符串只通过COM_STMT_PREPARE 调用一次发送到服务器(记录在here)。每次执行都是通过发送 COM_STMT_EXECUTE 来执行的,该 COM_STMT_EXECUTE 带有准备好的语句句柄和用于替换占位符的文字值。

    为了与客户端准备的示例进行对比,我们可以使用类似的代码块(但这次启用了服务器准备的语句):

    ps2=conn2.prepareStatement("select ?")
    ps2.setInt(1, 42)
    ps2.executeQuery()
    ps2.setInt(1, 43)
    ps2.executeQuery()
    

    日志会显示:

    254 Prepare    select ?
    254 Execute    select 42
    254 Execute    select 43
    

    您可以看到该语句在执行之前已准备好。日志帮了我们一个忙,显示了执行的完整语句,但实际上,每次执行时只有占位符值从客户端发送到服务器。

    缓存准备好的语句

    许多连接池将在使用连接时缓存准备好的语句,这意味着如果您调用conn.prepareStatement("select ?"),它将在使用相同语句字符串的连续调用中返回相同的PreparedStatement 实例。这有助于避免在事务之间将连接返回到池时重复在服务器上准备相同的字符串。

    MySQL JDBC 选项cachePrepStmts 将以这种方式缓存准备好的语句(客户端和服务器准备的语句)以及缓存语句的“可准备性”。 MySQL 中有一些语句在服务器端是无法准备的。如果驱动程序认为可能,它将尝试在服务器上准备一条语句,如果准备失败,则回退到客户端准备的语句。由于需要往返服务器,因此此检查成本很高。该选项还将缓存此检查的结果。

    希望这会有所帮助。

    【讨论】:

    • 很好的解释。我不知道客户端语句绑定值在发送到服务器之前在客户端被替换。
    • 似乎 useServerPrepStmts 属性默认是禁用的,即设置为 false,这基本上意味着大多数应用程序默认默认为客户端 PS?此外,考虑到 cachePrepStmts 默认也被禁用,它提供了什么意义/好处?
    猜你喜欢
    • 1970-01-01
    • 2019-01-19
    • 2023-03-12
    • 2015-01-20
    • 2011-08-14
    • 1970-01-01
    • 2016-10-16
    • 2013-03-14
    • 2017-05-19
    相关资源
    最近更新 更多