Java 将galera mariadb与jdbc结合使用

Java 将galera mariadb与jdbc结合使用,java,jdbc,mariadb,Java,Jdbc,Mariadb,我已经创建了一个mariadb集群,我正试图让一个Java应用程序在其中一个主机死亡时能够故障切换到另一个主机 我创建了一个应用程序,它创建了一个与jdbc:mysql:s的连接equential://host1,host2,host3/database?socketTimeout=2000&autoReconnect=true“。应用程序每秒在循环中进行一次查询。如果我杀死应用程序当前正在执行查询的节点(Statement.executeQuery()),我会因为超时而得到一个SQLExcep

我已经创建了一个mariadb集群,我正试图让一个Java应用程序在其中一个主机死亡时能够故障切换到另一个主机

我创建了一个应用程序,它创建了一个与jdbc:mysql:s的连接equential://host1,host2,host3/database?socketTimeout=2000&autoReconnect=true“。应用程序每秒在循环中进行一次查询。如果我杀死应用程序当前正在执行查询的节点(Statement.executeQuery()),我会因为超时而得到一个SQLException。我可以捕获异常并重新执行语句,我看到请求正在发送到另一台服务器,因此在这种情况下,故障转移可以正常工作。但我希望executeQuery()不会抛出异常并自动静默重试另一台服务器


假设我不必处理异常并明确地重试查询,这是错误的吗?我还需要配置其他配置吗?

自动重新连接是危险的,原因如下。假设您有以下代码:

BEGIN;
SELECT ... FROM tbl WHERE ... FOR UPDATE;
(line 3)
UPDATE tbl ... WHERE ...;
COMMIT;
现在让我们假设服务器在(第3行)崩溃。事务将回滚。在我虚构的示例中,这只涉及释放tbl上的锁

现在让我们假设在自动重新连接时,其他一些连接成功地在同一行上执行相同的事务

现在,通过自动重新连接,第一个线程忘记了事务的前半部分已回滚,并根据现在过期的数据继续执行更新

您需要获得一个异常,这样您就可以回到开始,这样您就可以“交易安全”

不管怎样,你都需要这样做——有了Galera,没有崩溃,类似的事情也会发生。两个线程同时在两个不同的节点上执行该事务。。。每一个都会成功,直到到达提交,此时Galera魔法发生,其中一个提交被告知失败。“正确”的响应是在选择失败的服务器上重播整个事务

请注意,与非Galera不同,Galera需要检查
COMMIT
上的错误


更多(针对从非Galera迁移的开发人员和DBA)

出于以下原因,自动重新连接是危险的。假设您有以下代码:

BEGIN;
SELECT ... FROM tbl WHERE ... FOR UPDATE;
(line 3)
UPDATE tbl ... WHERE ...;
COMMIT;
现在让我们假设服务器在(第3行)崩溃。事务将回滚。在我虚构的示例中,这只涉及释放tbl上的锁

现在让我们假设在自动重新连接时,其他一些连接成功地在同一行上执行相同的事务

现在,通过自动重新连接,第一个线程忘记了事务的前半部分已回滚,并根据现在过期的数据继续执行更新

您需要获得一个异常,这样您就可以回到开始,这样您就可以“交易安全”

不管怎样,你都需要这样做——有了Galera,没有崩溃,类似的事情也会发生。两个线程同时在两个不同的节点上执行该事务。。。每一个都会成功,直到到达提交,此时Galera魔法发生,其中一个提交被告知失败。“正确”的响应是在选择失败的服务器上重播整个事务

请注意,与非Galera不同,Galera需要检查
COMMIT
上的错误


更多(针对从非Galera迁移的开发人员和DBA)

故障转移并不意味着应用程序不必处理异常

当连接丢失时,驱动程序将尝试重新连接到另一台服务器

如果驱动程序无法重新连接到另一台服务器,将抛出SQLNonTransientConnectionException,池将自动放弃这些连接

如果恢复了连接,则在某些边缘情况下重新启动查询是安全的:例如,当查询不在事务中,并且连接当前在事务中时(使用Spring@Transactional(readOnly=false))。对于这些情况,mariadbjava连接将自动重新启动查询。在这些特定情况下,不会引发异常,故障切换是透明的

驱动程序无法在事务期间重新执行当前查询。
即使没有事务,如果查询是更新命令,驱动程序也无法知道数据库服务器是否已接收并执行了最后一个请求


然后驱动程序将发送一个SQLException(SQLState以“25”开头=INVALID_TRANSACTION_STATE),由应用程序处理这些情况

故障转移并不意味着应用程序不必处理异常

当连接丢失时,驱动程序将尝试重新连接到另一台服务器

如果驱动程序无法重新连接到另一台服务器,将抛出SQLNonTransientConnectionException,池将自动放弃这些连接

如果恢复了连接,则在某些边缘情况下重新启动查询是安全的:例如,当查询不在事务中,并且连接当前在事务中时(使用Spring@Transactional(readOnly=false))。对于这些情况,mariadbjava连接将自动重新启动查询。在这些特定情况下,不会引发异常,故障切换是透明的

驱动程序无法在事务期间重新执行当前查询。
即使没有事务,如果查询是更新命令,驱动程序也无法知道数据库服务器是否已接收并执行了最后一个请求


然后驱动程序将发送一个SQLException(SQLState以“25”开头=INVALID_TRANSACTION_STATE),由应用程序处理这些情况

谢谢。我没有意识到这一点。虽然这些信息对我很有用,但它并不能完全回答我的问题。您知道在查询过程中,如果出现故障,是否可以让驱动程序重新连接(而不是生成异常然后重新连接)。我有非常基本的问题