C# MySql长时间运行查询在Docker.NET Core上失败:试图读取超过流结尾的数据/预期读取4个头字节,但仅收到0
我试图用一个在非索引列上有where子句的查询来查询一个95M行的MySql数据库(请不要判断,我无法控制这部分,因为服务器不是我们的) 我尝试了MySqlConnector和MySqlClient,结果都是一样的。持续5分钟后,它们都会出错: 使用MySqlConnector: 应读取4个标头字节,但仅接收到0 使用MySql.Data.MySqlClient 试图读取超过流结尾的内容 此仅在docker容器中发生(在Windows上运行docker Desktop的C# MySql长时间运行查询在Docker.NET Core上失败:试图读取超过流结尾的数据/预期读取4个头字节,但仅收到0,c#,mysql,docker,.net-core,C#,Mysql,Docker,.net Core,我试图用一个在非索引列上有where子句的查询来查询一个95M行的MySql数据库(请不要判断,我无法控制这部分,因为服务器不是我们的) 我尝试了MySqlConnector和MySqlClient,结果都是一样的。持续5分钟后,它们都会出错: 使用MySqlConnector: 应读取4个标头字节,但仅接收到0 使用MySql.Data.MySqlClient 试图读取超过流结尾的内容 此仅在docker容器中发生(在Windows上运行docker Desktop的aspnet:3.1-bu
aspnet:3.1-buster-slim
图像,但我尝试了其他具有相同结果的方法)
通过IIS express托管的web api或控制台应用程序运行相同的代码可以正常工作
连接字符串指定连接超时=21600;默认命令超时=21600;最小池大小=0代码>我尝试了各种最小/最大池大小配置,并在没有运气的情况下关闭了池
我已尝试将连接字符串SslMode
更改为None
,但没有更改
查询数据的代码非常简单:
protected virtual async IAsyncEnumerable<List<object>> GetDataAsync(string connectionString, string sql, int timeout = 21600, IsolationLevel isolationLevel = IsolationLevel.ReadCommitted)
{
await using var conn = new MySqlConnection { ConnectionString = connectionString };
await conn.OpenAsync();
using var trans = await conn.BeginTransactionAsync(isolationLevel);
await using var cmd = new MySqlCommand { Connection = conn, CommandText = sql, CommandTimeout = timeout, Transaction = trans };
await using (var reader = await cmd.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
var values = new object[reader.FieldCount];
reader.GetValues(values);
yield return values.Select(v => v is DBNull ? null : v).ToList();
}
}
await trans.CommitAsync();
}
受保护的虚拟异步IAsyncEnumerable GetDataAsync(string connectionString,string sql,int timeout=21600,IsolationLevel IsolationLevel=IsolationLevel.ReadCommitted)
{
等待使用var conn=new MySqlConnection{ConnectionString=ConnectionString};
等待连接OpenAsync();
使用var trans=await conn.BeginTransactionAsync(隔离级别);
等待使用var cmd=new MySqlCommand{Connection=conn,CommandText=sql,CommandTimeout=timeout,Transaction=trans};
使用wait(var reader=wait cmd.ExecuteReaderAsync())
{
while(等待reader.ReadAsync())
{
var值=新对象[reader.FieldCount];
reader.GetValues(值);
产生返回值;
}
}
等待trans.CommitAsync();
}
我试过有交易和没有交易-没有变化
如果我尝试一个更简单的查询,我将使用相同的GetDataAsync
方法返回结果,而不考虑问题。更奇怪的是,其他长时间运行的查询也运行良好。如果我尝试对一个有3000万行的表执行类似的、无索引的查询,它会运行5分钟,最终(超过一小时)返回结果
运行show variables
会产生以下结果(其中似乎没有一个指向问题):
- 连接超时10
- 延迟插入超时300
- innodb\u在\u超时1时刷新\u日志\u
- innodb\u锁定\u等待\u超时50
- innodb\u回滚\u打开\u超时关闭
- 交互式超时28800
- 锁定等待超时31536000
- 网络读取超时30
- 净写入超时60
- rpl_停止_从站_超时31536000
- 从网络超时3600
- 等待超时28800
docker容器中是否出现某种空闲网络超时?在连接字符串中设置Keepalive=120
;这将每两分钟(120秒)发送TCP keepalive数据包,这将阻止连接关闭。(您可能需要根据具体情况调整Keepalive
值。)
请注意,如果您在Linux上使用MySqlConnector,由于.NET Core的限制,此选项仅在.NET Core 3.0(或更高版本)上实现。感谢您提出的详细问题和所有相关细节。但我不明白为什么30M行查询会运行一个小时,而95M行查询会在5分钟后超时。您是否在连接字符串中尝试了KeepAlive=120
,以强制TCP保留数据包?(MySqlConnector文档已经过时;该选项应该得到尊重,并在Linux上通过netcoreapp3.0
或更高版本实现。)赢家!!!谢谢你,@BradleyGrainger!!如果你想写下来作为答案,我很乐意接受。mysql和你引用的mysql.Data库的版本是什么?有一段时间也面临类似的问题back@KamranShahid我用最新版本的MySql.Data(v8.0.21)和MySqlConnector(v1.0.1)进行了尝试。多亏了布拉德利,我才能够使用MySqlConnector和KeepAlive=120
。我没有在MySql.Data上试过,我想他使用的是.NETCore3.1