连接释放问题 返回
我在压测数据过程中发现部分连接不释放,修改内容如下,修改后,连接释放。(Mysql 8.0.22)能否关注下,是否有帮助
QueryableProvider.cs
protected ListGetData(KeyValuePair<string, list> sqlObj)
{
try
{
Listresult;
var isComplexModel = QueryBuilder.IsComplexModel(sqlObj.Key);
var entityType = typeof(TResult);
var dataReader = this.Db.GetDataReader(sqlObj.Key, sqlObj.Value.ToArray());
result = GetData(isComplexModel, entityType, dataReader);
return result;
}
finally
{
this.Db.Close();
this.Db.Dispose();
}
}
protected async Task<list> GetDataAsync(KeyValuePair<string, list> sqlObj)
{
try
{
Listresult;
var isComplexModel = QueryBuilder.IsComplexModel(sqlObj.Key);
var entityType = typeof(TResult);
var dataReader = await this.Db.GetDataReaderAsync(sqlObj.Key, sqlObj.Value.ToArray());
result =await GetDataAsync(isComplexModel, entityType, dataReader);
return result;
}
finally
{
this.Db.Close();
this.Db.Dispose();
}
}
public virtual DataTable ToDataTable()
{
try
{
InitMapping();
var sqlObj = this.ToSql();
RestoreMapping();
DataTable result = null;
if (IsCache)
{
var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService;
result = CacheSchemeMain.GetOrCreate(cacheService, this.QueryBuilder, () => { return this.Db.GetDataTable(sqlObj.Key, sqlObj.Value.ToArray()); }, CacheTime, this.Context);
}
else
{
result = this.Db.GetDataTable(sqlObj.Key, sqlObj.Value.ToArray());
}
return result;
}
finally
{
this.Db.Close();
this.Db.Dispose();
}
}
public async Task<DataTable> ToDataTableAsync()
{
try
{
InitMapping();
var sqlObj = this.ToSql();
RestoreMapping();
DataTable result = null;
if (IsCache)
{
var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService;
result = CacheSchemeMain.GetOrCreate(cacheService, this.QueryBuilder, () => { return this.Db.GetDataTable(sqlObj.Key, sqlObj.Value.ToArray()); }, CacheTime, this.Context);
}
else
{
result = await this.Db.GetDataTableAsync(sqlObj.Key, sqlObj.Value.ToArray());
}
return result;
}
finally
{
this.Db.Close();
this.Db.Dispose();
}
}
AdoAccessory.cs
去除 protected IDbConnection _DbConnection;
AdoProvider.cs
将 AdoAccessory.cs 去除的 ,添加过来
public abstract partial class AdoProvider : AdoAccessory, IAdo
{
protected IDbConnection _DbConnection;
#region Constructor
public virtual void Dispose()
{
if (this.Transaction != null)
{
this.Transaction.Commit();
this.Transaction = null;
}
if (this.Connection != null && this.Connection.State != ConnectionState.Open)
{
this.Connection.Close();
this._DbConnection.Close();
}
if (this.Connection != null)
{
this.Connection.Dispose();
this._DbConnection.Close();
}
this.Connection = null;
if (this.IsMasterSlaveSeparation)
{
if (this.SlaveConnections != null)
{
foreach (var slaveConnection in this.SlaveConnections)
{
if (slaveConnection != null && slaveConnection.State == ConnectionState.Open)
{
slaveConnection.Dispose();
}
}
}
}
}
public virtual void Close()
{
if (this.Transaction != null)
{
this.Transaction = null;
}
if (this.Connection != null && this.Connection.State == ConnectionState.Open)
{
this.Connection.Close();
this._DbConnection.Close();
}
if (this.IsMasterSlaveSeparation && this.SlaveConnections.HasValue())
{
foreach (var slaveConnection in this.SlaveConnections)
{
if (slaveConnection != null && slaveConnection.State == ConnectionState.Open)
{
slaveConnection.Close();
}
}
}
}
热忱回答(41)
-
fate stay night VIP0
2020/11/23连接释放稳定这了么多年了,可能是你用法问题,
0 回复 -
fate stay night VIP0
2020/11/23如果有疑问不要轻易乱改代码,你这个代码我就已看出问题几个了,你可以写个控制台DEMO发给我我给你看
0 回复 -
fate stay night VIP0
2020/11/23我给你讲一下ado连接池机制,你并发请求 连接池不够就会开启多个连接池 每次操作完就会sleep这个连接池并且 下次在有新的请求会判段sleep的连接池是否存在,如果存在用sleep的连接池,连接字符串配置用默认的就好,sqlsugar置成自动释就行了 不建议你改任何一行代码
0 回复 -
fate stay night VIP0
2020/11/23.NET CORE3.0开始GC不会及时回收,你可以设置db.dispose 或者using实现C#对象的内存回收
0 回复 -
karqical VIP0
2020/11/23我是使用JMeter 进行的压测,我没有使用控制台进行测试。另外,我使用控制台,输出,压测之后,也发现,MySQLCommand 和MysqlConnection 的大量数据,我所说的这些内容都是使用JMeter 进行压测后的结论。
0 回复 -
fate stay night VIP0
2020/11/23@karqical:使用db.dispose就行了 你这个应该是core 3.0以上版本吧
0 回复 -
fate stay night VIP0
2020/11/23
.NET CORE 3之后内存回收机质有改动,如果你想手动释放C#内存一定要用 db.dispose或者using(db) 和数据库接池没有一点关系
0 回复 -
fate stay night VIP0
2020/11/23或者按上面设置成 false 也可以不使用db.dispose
0 回复 -
karqical VIP0
2020/11/23@fate stay night:好的,我先这么配置,再压测,谢谢你的帮助
0 回复 -
?下雪? VIP0
2020/11/23这是啥工具啊,这么好用的吗?求透露一下名字
0 回复 -
?下雪? VIP0
2020/11/23是他语文没学好吗,,,,咋感觉看起来说的话像机器翻译的。。
0 回复 -
karqical VIP0
2020/11/23@karqical:
@fate stay night:配置
falsefalse
并不起作用,内存依然上升。我想咨询下,SQLSugar 在高并发下,是否适合配置为单例。
0 回复 -
fate stay night VIP0
2020/11/23@karqical:不能单例,你看看 用完 db.dispose有效果没有
0 回复 -
fate stay night VIP0
2020/11/23@karqical:或者我写个代码给你测试一下
0 回复 -
fate stay night VIP0
2020/11/23你用的是什么数据库我写个代码出来
0 回复 -
karqical VIP0
2020/11/24@fate stay night:mysql 8.0.22
0 回复 -
karqical VIP0
2020/11/24@fate stay night:目前代码写成单例的方式,并且我测试过了,正常速度下,是不需要关心内存问题的,只有在频繁调用的时候,或者压测时,这个内存才增长。数据库使用Mysql 8.0.22
0 回复 -
fate stay night VIP0
2020/11/24@karqical:数据库操就不能用单例
0 回复 -
karqical VIP0
2020/11/24代码已经修改为创建,在单独的控制台测试,没有异常,在RPC 通信中有MysqlCommand 不是放的问题,我再看看
0 回复 -
fate stay night VIP0
2020/11/24@karqical:研究一下你那个 RPC 的GC回收机质吧, 只要能够和以前的项目一样像有自带的GC回收机质问题不大
0 回复 -
karqical VIP0
2020/11/24//sqlCommand.Dispose();
这里屏蔽掉的原因是什么呢 SqlSugar.AdoProvider.GetDataReaderAsync
public virtual async Task<IDataReader> GetDataReaderAsync(string sql, params SugarParameter[] parameters) { try { Async(); InitParameters(ref sql, parameters); if (FormatSql != null) sql = FormatSql(sql); SetConnectionStart(sql); var isSp = this.CommandType == CommandType.StoredProcedure; if (this.ProcessingEventStartingSQL != null) ExecuteProcessingSQL(ref sql, parameters); ExecuteBefore(sql, parameters); var sqlCommand = GetCommand(sql, parameters); var sqlDataReader = await sqlCommand.ExecuteReaderAsync(this.IsAutoClose() ? CommandBehavior.CloseConnection : CommandBehavior.Default); if (isSp) DataReaderParameters = sqlCommand.Parameters; if (this.IsClearParameters) sqlCommand.Parameters.Clear(); ExecuteAfter(sql, parameters); SetConnectionEnd(sql); //sqlCommand.Dispose(); return sqlDataReader; } catch (Exception ex) { CommandType = CommandType.Text; if (ErrorEvent != null) ExecuteErrorEvent(sql, parameters, ex); throw ex; } }0 回复 -
fate stay night VIP0
2020/11/24@karqical:考虑到可能是outpust参数之后的东西要返回,所以才去掉了这个代码 让GC去回收
0 回复 -
fate stay night VIP0
2020/11/24去掉应该是有原因的,具体什么原因我暂时也想不起来
0 回复 -
fate stay night VIP0
2020/11/24你在测一下和驱动版本有没有关系
0 回复 -
karqical VIP0
2020/11/24@fate stay night:可能当时用的Mysql.Data 插件在 8.0.20. 以下,这里使用MysqlCommand.dispose 会报错误(https://bugs.mysql.com/bug.php?id=89159),可能就是这个原因吧。
0 回复 -
fate stay night VIP0
2020/11/24@karqical:时间比较久了不记得了,不过GC回收正常应该可以释放的
0 回复 -
fate stay night VIP0
2020/11/24我这边在加上去测测
0 回复 -
fate stay night VIP0
2020/11/24@karqical:如果低版本报错的话可能就是那个问题
0 回复 -
fate stay night VIP0
2020/11/24@karqical:新版本优化了一下你试试看
0 回复 -
胖??骆驼 VIP0
2020/11/25@fate stay night:哪个版本开始优化的?
0 回复 -
karqical VIP0
2020/11/25@fate stay night:很棒,效果很明显,新版中 MysqlCommand 已经自动释放了。剩下就是MySQLConnection 的问题,压测中,发现修改如下代码后,MySQLConnection的溢出不在增长。

SqlSugar.QueryableProvider.GetDataAsync protected async Task<List<TResult>> GetDataAsync<TResult>(KeyValuePair<string, List<SugarParameter>> sqlObj) { try { List<TResult> result; var isComplexModel = QueryBuilder.IsComplexModel(sqlObj.Key); var entityType = typeof(TResult); var dataReader = await this.Db.GetDataReaderAsync(sqlObj.Key, sqlObj.Value.ToArray()); result =await GetDataAsync<TResult>(isComplexModel, entityType, dataReader); return result; } finally { this.Db.Close(); this.Db.Dispose(); } }0 回复 -
fate stay night VIP0
2020/11/25@karqical:不能这么改的,你用我最新版本测试
using(sqlsugarclient db=new sqlsugarclient)
{
}
或者
sqlsugarclient db=new sqlsugarclient
db.dispose
应该解决了人的问题,哪怕你GC不回收也可以处理
0 回复 -
fate stay night VIP0
2020/11/25@karqical:不要想着改我的代码你这么改是有大问题的 ,最新版本已经按你要求处理过了
0 回复 -
karqical VIP0
2020/11/25@fate stay night:好的。目前没有改动。
0 回复 -
karqical VIP0
2020/11/25@fate stay night:
更新版本5.0.1.4后,使用如下配置和代码,当字段为 null 会报错:
/// <summary> /// 创建人Id /// </summary> [SugarColumn(IsNullable =true)] public Guid? CreatedUserId { get; set; } Mysql 字段使用char(36)错误为:
System.AggregateException: One or more errors occurred. (English Message : Entity mapping error.Non-negative number required. (Parameter 'count') Chinese Message : 实体与表映射出错。Non-negative number required. (Parameter 'count')) ---> SqlSugar.SqlSugarException: English Message : Entity mapping error.Non-negative number required. (Parameter 'count') Chinese Message : 实体与表映射出错。Non-negative number required. (Parameter 'count')
我把
Mysql 字段使用varchar(36)
错误消失。
或者回退到版本5.0.0.14 这里不需要修改.
0 回复 -
fate stay night VIP0
2020/11/25@karqical:你这个是.NET CORE 5.0才出现的吗?
0 回复 -
karqical VIP0
2020/11/26@fate stay night:目前我还是用的 .net core 3.1,net core 5.0 还没有试过
0 回复 -
fate stay night VIP0
2020/11/26@karqical:这个问题后面修复
0 回复 -
fate stay night VIP0
2020/11/26@karqical:经过我的测试这个是驱动BUG 暂时不能解决只能等新版本的mysq.data驱动一起更新
using (var re = Db.Ado.GetDataReader("select * from UnitTAFA1")) { while (re.Read()) { } }public class UnitTAFA1
{
public string name { get; set; }
[SugarColumn(IsNullable = true, ColumnDataType = "char(36)")]
public Guid? a { get; set; }
}
.
0 回复 -
fate stay night VIP0
2020/11/26或者你不插入null
0 回复 -
karqical VIP0
2020/11/26@fate stay night:为了系统能用,我把数据库 字段是 char36 都改成varchar(36) 了
0 回复