MySQL Connector/J 支持服务器故障转移。当底层活动连接发生与连接相关的错误时,就会发生故障转移。默认情况下,连接错误会传播到客户端,客户端必须通过例如重新创建工作对象( 、 等)和重新启动进程来Statement
处理
ResultSet
它们。有时,驱动程序最终可能会在客户端应用程序继续运行之前自动回退到原始主机,在这种情况下,主机切换是透明的,客户端应用程序甚至不会注意到它。
使用故障转移支持的连接就像标准连接一样工作:客户端在故障转移过程中不会遇到任何中断。这意味着客户端可以依赖同一个连接实例,即使两个连续的语句可能在两个不同的物理主机上执行。但是,这并不意味着客户端不必处理触发服务器切换的异常。
故障转移是在服务器连接的初始设置阶段通过连接 URL 配置的(请 在此处查看其格式的解释):
jdbc:mysql://[primary host][:port],[secondary host 1][:port][,[secondary host 2][:port]]...[/[database]]»
[?propertyName1=propertyValue1[&propertyName2=propertyValue2]...]
连接 URL 中的主机列表包括两种类型的主机,主要主机和次要主机。启动新连接时,驱动程序始终首先尝试连接到主要主机,如果需要,在遇到通信问题时按顺序故障转移到列表中的辅助主机。即使与主要主机的初始连接失败并且驱动程序连接到次要主机,主要主机也永远不会失去其特殊地位:例如,它可以配置为不同于次要主机的访问模式,并且它当在故障转移过程中选择主机时,可以将其置于更高的优先级。
故障转移支持由以下连接属性配置(它们的功能在下面的段落中解释):
failOverReadOnly
secondsBeforeRetrySource
queriesBeforeRetrySource
retriesAllDown
autoReconnect
autoReconnectForPools
配置连接访问模式
与任何标准连接一样,与主要主机的初始连接处于读/写模式。但是,如果驱动程序无法与主要主机建立初始连接并自动切换到列表中的下一个主机,则访问模式现在取决于属性的值
failOverReadOnly
,即
“ true ”默认。如果驱动程序最初连接到主要主机,并且由于某些连接失败,它会故障转移到辅助主机,也会发生同样的情况。每次连接回退到主要主机时,其访问模式将是读/写,而不管之前是否连接过主要主机。 Connection.setReadOnly(boolean)
连接访问模式可以在运行时通过调用部分覆盖属性
的方法随时更改failOverReadOnly
。当
failOverReadOnly=false
访问模式明确设置为 true 或 false 时,它成为主机切换后每个连接的模式,无论连接到哪种主机类型;但是,如果
failOverReadOnly=true
,只有当驱动程序连接到主要主机时,才能将访问模式更改为读/写;然而,即使无法更改当前连接的访问模式,驱动程序也会记住客户端的最后意图,并且在回退到主要主机时,这就是将要使用的模式。有关说明,请参阅以下具有双主机连接的事件序列。
序列 A,其中
failOverReadOnly=true
:以读/写模式连接到主要主机
套
Connection.setReadOnly(true)
;主要主机现在处于只读模式故障转移事件;以只读模式连接到辅助主机
套
Connection.setReadOnly(false)
;辅助主机保持只读模式回退到主要主机;连接现在处于读/写模式
序列 B,与
failOverReadOnly=false
以读/写模式连接到主要主机
套
Connection.setReadOnly(true)
;主要主机现在处于只读模式故障转移事件;以只读模式连接到辅助主机
设置
Connection.setReadOnly(false)
;连接到辅助主机切换到读/写模式回退到主要主机;连接现在处于读/写模式
这两种情况的区别在于第 4 步:序列 A 中的辅助主机的访问模式在那一步没有改变,但驱动程序会记住并在回退到主要主机时使用设置的模式,这将是 read-只有否则;但在序列 B 中,辅助主机的访问模式立即发生变化。
配置回退到主要主机
如前所述,当涉及到主机的访问模式时,主主机在故障转移安排上是特殊的。此外,驱动程序默认会尝试尽快回退到主要主机,即使没有发生通信异常也是如此。两个属性
secondsBeforeRetrySource
和
queriesBeforeRetrySource
确定驱动程序何时准备好重试与主要主机的重新连接(
Source
属性名称中的 代表我们连接 URL 的主要主机,它不一定是复制设置中的源主机):
secondsBeforeRetrySource
确定驱动程序在尝试回退到主要主机之前等待的时间queriesBeforeRetrySource
确定在驱动程序尝试回退到主要主机之前执行的查询数。请注意,对于驱动程序,每次调用Statement.execute*()
方法都会增加查询执行计数器;因此,当调用Statement.executeBatch()
or ifallowMultiQueries
或rewriteBatchStatements
enabled 时,驱动程序可能无法准确计算在服务器上执行的查询的实际数量。Statement.execute*()
此外,驱动程序会在多种情况下在内部调用这些方法。所有这些意味着您只能将queriesBeforeRetrySource
其用作何时回退到主要主机的粗略规范。
通常,当至少满足两个属性指定的条件之一时,就会尝试回退到主要主机,并且尝试总是在事务边界发生。但是,如果关闭自动提交,则仅在调用方法
Connection.commit()
或
时才会进行检查Connection.rollback()
。secondsBeforeRetrySource
可以通过同时将和
设置queriesBeforeRetrySource
为“ 0 ”来关闭对主要主机的自动回退
。仅将其中一个属性设置为“ 0 ”只会禁用一部分检查。
配置重新连接尝试
当建立新连接或发生故障转移事件时,驱动程序会尝试连续连接到主机列表中的下一个候选者。当到达列表的末尾时,它会从列表的开头重新开始;但是,如果 (a) 并非所有次要主机都已经至少测试过一次,并且 (b) 和 (b) 定义的回退条件尚未满足,则将跳过主要
secondsBeforeRetrySource
主机
queriesBeforeRetrySource
。每次遍历整个主机列表(不一定在主机列表末尾完成)都算作一次连接尝试。驱动程序尝试的连接尝试次数与属性值指定的次数相同
retriesAllDown
。
无缝重连
尽管不推荐,您可以通过将参数或
设置为
使驱动程序执行故障转移而不使活动
Statement
或ResultSet
实例
无效autoReconnect
autoReconnectForPools
true
. 这允许客户端在故障转移事件后继续使用相同的对象实例,而无需采取任何异常措施。然而,这可能会导致意想不到的结果:例如,如果驱动程序以读/写访问模式连接到主要主机,并且它以只读模式故障转移到辅助主机,则进一步尝试发出数据更改查询将导致错误,而客户端不会意识到这一点。在使用数据流时,此限制尤为重要:故障转移后,
ResultSet
看起来没问题,但底层连接可能已经更改,并且不再有可用的后备游标。
使用带有 DNS SRV 的 JDBC 配置服务器故障转移
有关详细信息,请参阅第 3.5.14 节“支持 DNS SRV 记录”。