这个也是我想说的,我也觉得是这个原因
经过以上大量实践,有很多我自己没办法解释的事情:
1.多个客户我都给他们上的是Oceanbase,版本和配置也都一致:5.7.25-OceanBase_CE-v4.3.3.1
2.我们开发使用C#.NET,数据库驱动用的是mysqlconnector(2.3.7)默认开启连接池,只要使用连接池,第二次必出问题,第一次没事,但是其他客户Oceanbase即便是开了连接池也没问题。测试代码也相同
3.超时时间7个0是Oceanbase的默认值,我怀疑被重置成了默认值,但是应该不是客户端发起更改的,因为Mysqlconnector官方是没有刻意支持Oceanbase的,只是Oceanbase彻底兼容了MySQL,所以Mysqlconnector不会为Oceanbase做什么刻意的逻辑。
4.原以为彻底重启Oceanbase集群会解决问题,,昨晚重启之后运行测试代码确实没问题了,但是早上一看还是不行,又回到老样子
上面测试代码里 不要用 set global 设置,而改为 set ob_query_timeout 去设置,然后读设置的结果,再看看。理论上能看到设置后的值。
另外在你跑测试期间,分析一下 连接用的obproxy 的日志 obproxy.log,里面有客户端发出的所有的sql的日志,包括这些 set 命令。看看里面有没有什么发现。
日志上面回复有,其实测试代码的set指令不重要。去掉一样不影响测试结果。因为之前已经通过命令行set global了。
set global 语句只是改变租户全局的设置,对当前会话不生效。新开的会话如果不设置这个会继承这个 全局的设置。但是如果新会话开启了 set [session] 的设置,又会有自己的的值。
像上面那段代码,如果前面用 set 设置,后面用 show variables 读取,这里应该读取到的就是前面设置的值。后面的 select 就不应该报超时。先确认这段逻辑符合预期。如果不符合,那估计就是数据库 bug(这个可能性很低,ob 这块逻辑很成熟)。
当上面这段代码符合预期后,去掉 set 语句,超时参数又变为默认的,则有可能是这个驱动连接哪个地方也设置了这个参数值。这个就需要查看 obproxy.log 去看连接的建立。
在分析的时候先去掉应用连接池的设置,因为连接池里连接可以复用,可能对这个分析有一定干扰。最前面的代码 for 循环里创建连接,拿到的连接可能是复用连接池里的连接。 如果应用都是每次重新启动,这个怀疑也不是那么的有说服性。不过先不用连接池在一个简单的场景下分析问题还是容易一些。
最后才是到用连接池的情形下测试。
最新的测试代码
开启连接池就有问题,如果关闭连接池,两次都能输出2000000000
注:运行测试代码前已经通过navicat设置了set global ob_query_timeout=2000000000;
查询审计:oceanbase.GV$OB_SQL_AUDIT视图
obproxy.log (107.7 KB)
还是那个问题,
则有可能是这个驱动连接哪个地方也设置了这个参数值。
MysqlConnector不是为Oceanbase开发的,是为MySQL开发的驱动,里面不会有设置ob_query_timeout的代码(甚至我下载了MysqlConnector源码进行了搜索),或者说Oceanbase除了set ob_query_timeout指令可以设置超时时间,有没有其他方式来设置超时,让MysqlConnector连接池下不小心给设置了?
纠正一下。之前提到我们有其他客户的Oceanbase,出问题的这个客户版本是
5.7.25-OceanBase_CE-v4.3.3.1
只有他们一家用的这版本
其他客户使用的
5.7.25-OceanBase_CE-v4.3.0.1
5.7.25-OceanBase_CE-v4.3.4.0
这两个版本没问题,我有点怀疑是4.3.3.1版本的问题了,晚上升级看看
学习学习
升级完Oceanbase到v4.3.4.0版本之后再次测试问题仍不能解决。见鬼了。暂时没其他排查思路了,有能力的兄弟根据上面的日志和描述看看有没有其他我可以尝试的方法吧,感谢
麻烦官方关注一下,客户环境ERP因为这个事一个月的日结没跑成功了,如果有必要的话我可以提供远程控制
你的测试 通过直连2881和通过obproxy都有问题是么?obproxy的版本发一下
直连2881的、因为只有一台机器,没有使用obproxy,
部署了12个客户了, 同一套产品代码, 就这一台服务器出现这么诡异的现象,一使用客户端连接池就出问题,强行关闭连接池没问题。
试了一下使用2883 obproxy连接,出现了新的问题。 客户端驱动Mysqlconnector明明指定了使用连接池,但是每次最终是没走连接池的,依据是查询gv$ob_processlist的的连接id(id列)
obproxy版本:
obproxy (OceanBase 4.3.2.0 26)
REVISION: 1-local-bc486e6c0fc5869b0265ec5dd9870ccfa6bcf15c
BUILD_TIME: Oct 22 2024 11:17:18
因为使用了obproxy后连接池废掉,每次都是打开新的连接,所以ob_query_timeout返回正常。
但是业务的情况我们是不能废掉连接池的,所以不能用obproxy
使用Obproxy无法启用连接池的问题找到了,是默认obproxy返回的版本号5.6.25过低导致Mysqlconnector驱动认为驱动不支持连接池导致的,修改ALTER proxyconfig SET mysql_version = ‘5.7.25’;之后2883也能走连接池了
但是使用obproxy2883和直连2881的结果是一样的,都是第一次连接查询返回的ob_query_timeout是对的,第二次是Oceanbase官方默认值10000000。
2881和2883都有问题
好的 感谢你的分享
但是我的问题还没解决,我仔细看了Mysqlconnector的源码,在配置启用连接池的情况下第二次open一个连接,会先向服务器发起 reset_connection 指令。我修改驱动源码让它绕过这个指令就一切正常了,但是这样有其他副作用。能不能从这个视角分析一下问题在哪里?
mysql关于reset-connection的文档
MySQL :: MySQL 5.7 C API 开发指南 :: 5.4.60 mysql_reset_connection()
好的 我们本地也测试一下 后续有消息了 信息同步给你
using var connection = new MySqlConnection(connectionString);
connection.Open();
using var command1 = new MySqlCommand("SHOW VARIABLES LIKE 'ob_query_timeout'", connection);
var o = command1.ExecuteScalar();
DataSet ds = new DataSet();
Console.WriteLine($"连接ID:{connection.ServerThread} ob_query_timeout=" + o);
Console.WriteLine("");
//发起 mysql_reset_connection
await connection.ResetConnectionAsync();
using var command2 = new MySqlCommand("SHOW VARIABLES LIKE 'ob_query_timeout'", connection);
var o2 = command1.ExecuteScalar();
DataSet ds2 = new DataSet();
Console.WriteLine($"连接ID:{connection.ServerThread} ob_query_timeout=" + o2);
Console.WriteLine("");
await Task.FromResult(0);
结果:
连接ID:-1073470632 ob_query_timeout=1000000000
连接ID:-1073470632 ob_query_timeout=10000000
更新示例代码,不用连接池,只要调用ResetConnectionAsync,我的一台Oceanbase集群上必现。
但是疑惑的是我有10几个独立的Oceanbase集群,只有这一个有问题,这一个还必现问题
observer.log
结合上面贴出来的Oceanbase源码,被重置了
o.log (4.0 MB)