-
Notifications
You must be signed in to change notification settings - Fork 342
MySqlConnector.MySqlException in TransactionScope.Dispose caused by a deadlock creates a memory leak #1317
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Does #1318 seem like a reasonable fix for this issue? |
Thanks for the quick reply @bgrainger! To answer your question, it does indeed seem like a reasonable fix to me 👍, it would definitely fix our scenario. I'm just wondering if you want the try/catch in all scenario's and not just explicitly when calling the ExecuteXaCommand with "ROLLBACK" (or for simplicity only in the OnRollback method), but I'll leave that up to you to decide, I have too little understanding of the internals of the library/package. |
Yes, that's a good callout; it probably makes more sense to have a targeted exception handler just in |
Sounds good @bgrainger, thanks 👍 |
Fixed in 2.2.6. |
Thanks! The coming days we'll test the new package to see if the memory leak is gone. |
Memory is really stable now, memory leak is solved. Thanks again! |
Software versions
MySqlConnector version: 2.2.5
Server type (MySQL, MariaDB, Aurora, etc.) and version: 10.6.12-MariaDB-log
.NET version: 6.0
Describe the bug
When a deadlock is thrown by the SQL database, we catch and retry it as suggested by the exception. But before we retry, our using statement inside our try/catch block disposes of the then active TransactionScope. The dispose however is interrupted by another exception thrown by MySqlConnector, causing the TransactionScope to not be properly disposed and leaving behind a reference in the s_transactionConnections dictionary which will snowball into ever increasing memory leakage for each subsequently created transaction.
Exception
Code sample
Not available, scenario should be easy enough to replicate and the exception holds all necessary information.
Expected behavior
The transaction dispose should preferably not be interrupted by exception, but in the case it has to, it should ensure that any static references bound to the transaction are still properly cleaned up.
Additional context
The reason why I consider this a 'severe' memory leak is the following;
Once the transaction is stuck inside the s_transactionConnections dictionary everything that's referenced by it is no longer eligible for garbage collection, this wouldn't be that bad if it was just the transaction, but in .NET adds data for every subsequently created transaction to those references which will then also never be eligible for garbage collection.
To be more specific, each transaction holds a reference to an InternalTransaction, which in term holds a reference to a Bucket, which has a reference to a BucketSet to which it belongs. Each BucketSet holds a weak-reference to it's previous BucketSet and a hard-reference to the next BucketSet. Any newly created Transaction will insert a new BucketSet into the chain of BucketSets ordered by an 'AbsoluteTimeout' value (hard referencing is done oldest->newest).
This means that our old BucketSet will keep newer BucketSets in memory forever, eventually causing an application that ran into a deadlock to inevitably run out of memory.
The text was updated successfully, but these errors were encountered: