场景分析
以 APP<->OBProxy<->OBServer 链路为例。
客户端断开 SQL 连接
客户端断开 SQL 连接的原因可能包括。
最常见的原因就是 APP 在 SQL 执行未完成的情况下主动断开了连接 (主动 kill session, 判断执行超时关闭连接,网络/机器异常导致和 OBProxy 间 TCP 连接保活超时等),此时 OBProxy 感知到也会断开和 OBServer 之间的连接,当 SQL 在执行过程中或执行完成后发现 SQL 连接已经断开了,则需要主动断开 SQL 连接,这时候就会调用
force_disconnect去关闭连接并完成对应 session 的清理。这种场景下该日志只是表示客户端断开了连接,OBServer 也需要关闭连接。典型的合并场景下触发
force_disconnect。- 正常来说应用采用这种方式进行连接
APP<->OBProxy<->OBServer1,当进行合并的时候 OBProxy 收到了com_quit命令,由于 OBServer1 正在合并,OBProxy 会选择发送到 OBServer2,发送到 OBServer2 时会先发送set @@xxx=xxx;这样的环境变量,当同步这些变量时由于 APP 已经把连接给断开了,这时 OBProxy 会把这个 APP 对应的所有 server 连接都退出,导致 OBServer2 在执行set @@xxx=xxx;时因为连接断开而报错,该问题对 OBServer 和应用都无任何影响。
- 正常来说应用采用这种方式进行连接
SQL 执行时状态异常或输入条件异常
SQL 执行时检测到某些状态异常或者输入条件异常时,此时即使给客户端回错误码,客户端也不知道该怎么处理,此时会主动断开连接。
以下是具体的子场景。
SQL parse 之前出错。
不返回客户端包,服务器端主动断开连接。
SQL parse 出错。
如果 parser 的返回码为以下错误码,则认为是正常的错误,向客户端返回真实的错误码,不断连接。
OB_ERR_EMPTY_QUERY(空请求), OB_ERR_PARSE_SQL(语法错误), OB_SIZE_OVERFLOW(内存不足)。否则认为是不正常的错误,不给客户端回包,服务端主动断开连接。
SQL parse 结束之后但是还没调用事务层的
end trans接口前已出错。commit 和 rollback 语句。
不给客户端回包,服务端主动断开连接。
普通的 DML 语句。
如果还没调用
partition service的end trans接口就出错了,那么向客户端返回真实的错误码,不断连接。如果已经调用了
partition service的end trans接口,但是还没调用事务层的end trans接口就出错了,则不给客户端回包,服务端主动断开连接。
调用事务层的
end trans接口出错。隐式和显式 commit 出错。
遇到以下错误码,向客户端返回真实的错误码,不断连接。
OB_TRANS_KILLED, OB_TRANS_CTX_NOT_EXIST, OB_TRANS_TIMEOUT, OB_TRANS_STMT_TIMEOUT, OB_TRANS_NEED_ROLLBACK, OB_TRANS_ROLLBACKED, OB_NOT_MASTER, OB_TRANS_IS_EXITING。否则,不给客户端回包,服务端主动断开连接。
显式 rollback 出错。
由于客户端就算收到错误码也不知道怎么处理,因此不给客户端回包,服务端主动断开连接。
隐式 rollback 出错。
向客户端返回真实的错误码,不断连接。这里最开始是做成断连接的,但是由于
autocomit=1的分布式查询经常会遇到 rollback 失败,所以才做成不断连接的,这样一来,客户端有可能会受到奇怪的错误码,但是没有关系,服务端会清除掉这个事务的状态,客户端接下来无论发什么请求都不会影响到这个事务了。调用事务层的
end trans接口成功,但是在给客户端回包之前或者过程中出错。如果还没回包,则不给客户端回包,断开连接;如果已经回包,则直接断开连接。
适用版本
OceanBase 数据库所有版本。