某项目进行中,因为分布式多线程的缘由,项目需要频繁的启用新的数据库连接,在系统启动几小时后系统出现数据库连接池不够导致数据库连接不成功。
项目使用了DevExpress XPO
数据库采用的是MySQL V5.7.31
报错信息(类似的,下面是SQL Server的报错信息):
DevExpress.Xpo.DB.Exceptions.UnableToOpenDatabaseException
HResult=0x80131500
Message=无法打开数据库。连接字符串:“data source=192.168.1.202;user id=sa;password=***REMOVED***;initial catalog=Set;Persist Security Info=true;”;错误:'System.InvalidOperationException: 超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。
在 System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
在 System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
在 System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
在 System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
在 System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
在 System.Data.SqlClient.SqlConnection.Open()
在 DevExpress.Xpo.DB.MSSqlConnectionProvider.CreateDataBase(SqlConnection conn)“
Source=DevExpress.Xpo.v19.1
StackTrace:
在 DevExpress.Xpo.DB.MSSqlConnectionProvider.CreateDataBase(SqlConnection conn)
在 DevExpress.Xpo.DB.MSSqlConnectionProvider.CreateDataBase()
在 DevExpress.Xpo.DB.ConnectionProviderSql..ctor(IDbConnection connection, AutoCreateOption autoCreateOption)
在 DevExpress.Xpo.DB.MSSqlConnectionProvider..ctor(IDbConnection connection, AutoCreateOption autoCreateOption)
在 DevExpress.Xpo.DB.MSSqlConnectionProvider.CreateProviderFromString(String connectionString, AutoCreateOption autoCreateOption, IDisposable[]& objectsToDisposeOnDisconnect)
在 DevExpress.Xpo.DB.DataStoreBase.QueryDataStore(String providerType, String connectionString, AutoCreateOption defaultAutoCreateOption, IDisposable[]& objectsToDisposeOnDisconnect)
在 DevExpress.Xpo.XpoDefault.GetConnectionProvider(String connectionString, AutoCreateOption defaultAutoCreateOption, IDisposable[]& objectsToDisposeOnDisconnect)
在 DevExpress.ExpressApp.Xpo.ConnectionStringDataStoreProvider.CreateWorkingStore(IDisposable[]& disposableObjects)
在 DevExpress.ExpressApp.Xpo.XPObjectSpaceProvider.CreateObjectSpace(Func`1 objectSpaceDelegate)
在 DevExpress.ExpressApp.Xpo.XPObjectSpaceProvider.CreateObjectSpace()
在 SuperNest_DB_Test.Form1.button1_Click(Object sender, EventArgs e) 在 C:\Users\DELL\source\repos\SuperNest_DB_Test\SuperNest_DB_Test\Form1.cs 中: 第 52 行
在 System.Windows.Forms.Control.OnClick(EventArgs e)
在 System.Windows.Forms.Button.OnClick(EventArgs e)
在 System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
在 System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
在 System.Windows.Forms.Control.WndProc(Message& m)
在 System.Windows.Forms.ButtonBase.WndProc(Message& m)
在 System.Windows.Forms.Button.WndProc(Message& m)
在 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
在 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
在 System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
在 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
在 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
在 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
在 System.Windows.Forms.Application.Run(Form mainForm)
在 SuperNest_DB_Test.Program.Main() 在 C:\Users\DELL\source\repos\SuperNest_DB_Test\SuperNest_DB_Test\Program.cs 中: 第 19 行
此异常最初是在此调用堆栈中引发的:
[外部代码]
内部异常 1:
InvalidOperationException: 超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。
下面代码展示了如何在无数据库连接的情况下业务逻辑照样开展,以及在有数据库连接时对数据库连接池做可控管理:
IDataLayer dataLayer = null;
UnitOfWork uow = null;
try
{
string connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
dataLayer = XpoDefault.GetDataLayer(connectionString, DevExpress.Xpo.DB.AutoCreateOption.DatabaseAndSchema);
uow = new UnitOfWork(dataLayer);
}
catch (Exception ex)
{
logHelper.ErrorOnce($"ClientID:{ClientID} Connecting the mysql database.Error message: {ex.Message}");
}
Program nc;
if (uow != null)
{
nc = new Program(uow);
}
else
{
nc = new Program();
}
.....
if (uow != null)
{
uow.CommitChanges();
}
try
{
if (uow != null)
{
uow.Disconnect();
uow.Dispose();
}
if (dataLayer != null)
{
dataLayer.Dispose();
}
}
catch (Exception ex)
{
logHelper.ErrorOnce($"DEVICE:{deviceID} Error message: {ex.Message}。StackTrace: {ex.StackTrace}");
}