给connection设置了sql_log_bin=0后,将connection归还给hikari,sql_log_bin=0还生效吗?
答案是:不会安全生效,如果直接把 Connection
归还给 Hikari 连接池,sql_log_bin=0
可能会影响下一个使用该连接的 SQL,本文来详细探讨一下:
1️⃣ Hikari 连接池的行为
- Hikari 使用 连接池复用,从池中取出的
Connection
可能之前已经被其他线程使用过。 sql_log_bin
是 MySQL 会话级变量,属于该连接的状态。- 如果你在方法里执行
SET sql_log_bin=0
,然后归还连接:
- 连接池不会自动重置
sql_log_bin
, - 下一个线程从池中取到这个连接时仍然可能是
0
,导致本应写入 binlog 的操作也不会写。
2️⃣ 正确做法
为了保证 连接池安全,必须在使用完成后 立即恢复 sql_log_bin=1
,或者在 Hikari 层做初始化:
方法 A:方法执行前后手动恢复
try (Statement stmt = conn.createStatement()) {
stmt.execute("SET sql_log_bin=0"); // 执行 SQL 不写 binlog
}
// 执行原方法...
try (Statement stmt = conn.createStatement()) {
stmt.execute("SET sql_log_bin=1"); // 恢复
}
这种方式是我们前面 AOP 实现的方式,保证连接在归还前已经恢复。
方法 B:Hikari 初始化 SQL
Hikari 支持配置 每次取连接时执行的初始化 SQL,确保归还连接状态安全:
spring:
datasource:
hikari:
connection-init-sql: SET sql_log_bin=1
- 每次从连接池获取连接时,Hikari 会执行
SET sql_log_bin=1
,保证默认状态正确。 - 然后我们在方法里临时执行
SET sql_log_bin=0
,方法结束归还前恢复即可。
3️⃣ 小结
- 直接归还连接,不恢复
sql_log_bin
是不安全的 - 必须在方法结束前恢复为
1
- 最稳妥方式:
- Hikari 配置
connection-init-sql=SET sql_log_bin=1
- AOP 或拦截器临时设置
0
并在 finally 块恢复
这样就可以同时满足 多数据源 + 连接池安全 + binlog 控制。