-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Underlying locking changes have broken async transactions #881
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
We're seeing this issue too with the latest release. Setting |
This may be possible but then all read operations would lock as well. Regardless this seems like a break in the API. The original question still stands.
|
Setting
Whether or not this change is intentional is beyond me, I'm new here 🤷♂ |
This could explain why i am seeing |
I have also noticed this all of a sudden. It seems to randomly show up and cause errors in my app. Just would like to know if this was by design, so I can begin mitigating, or should I downgrade and wait for a fix? |
For now I am holding off upgrading to this release until some feedback is provided. |
I am having the same issue after upgrading to version 1.6.292. A multi-thread transactions throws |
I think this could be the real issue I am facing after initially focusing my efforts on this thread: I too have seen random "Databse is locked" recently and I think it may be linked to this |
I had this issue as well and reverted to prev nuget version as my apps were dying with many crash reported. It's also a little scary that @praeclarum isn't replying to any of these issues leaving us the only option to rollback. |
I think this is the best fix, does anyone know how to fix the small sample using
|
We ended up using
|
Heres some helper methods to add to your data access:
used like:
I suggest creating a wrapper class for all DataAccess calls Also be careful not to nest the |
There is a slight performance impact of locking this way. Out of interrest, does anyone know if we should we be locking both |
Sqlite-net's old behavior created a secondary read-only database connection for reading while the read-write connection was locked. The current implementation uses a single unlocked read-write connection, which is the source of this change in behavior. The secondary connection made it safe to read without locking, since it made it impossible for an async read operation to interfere with a concurrent transaction. That is no longer the case, so yes, you should be locking both |
Concerning JKennedy24's contribution, I still get a random "database is locked" message. Darn. Heres some helper methods to add to your data access:
used like:
|
I spoke too soon. After looking at Kennedy's code again, I added a static to the first line: |
@praeclarum do you care to comment at all on this? |
We have the same issue in our apps. We have the "Cannot begin a transaction while already in a transaction" exception after upgrading of the sqlite-net-pcl library to version 1.6.292. We created a workaround in our code using the SemaphoreSlim class like this:
It works fine. But we decided to downgrade the sqlite-net-pcl library back to version 1.5.231 before an answer from the author is not provided. |
* Downgrade back to v1.5.231 * v1.6.292 seems to have lock/mutex issues with async methods * Reference: praeclarum/sqlite-net#881
Same problem for me. I'm using the 1.6.292 version and lately I noticed a lot of worrying errors related to SQLite database. We use a SQLiteConnectionString with encryption , these SQLiteOpenFlags: SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.FullMutex These are the most common problems we are facing it:
obviously, the problems appears randomly, in a not reproducible way, and we already have done assesments about code (checking that all the transactions don't use the async connection inside) and about permissions |
surprising how something so fundamental to modern applications can be so unsupported and broken. Why has no one from Microsoft picked up/forked this project? |
Maybe because of EF Core which you can pretty much use as a replacement for this. |
I was wondering whether everyone was using an alternative that had passed me by. This is going to be the 2nd time I've changed my database engine in my project since starting it 5 years ago. as some background I am developing a Xamarin.forms application @diegostamigni can you share some links to nugets / github repos and project type you are working on to point me / others in the right direction for alternatives? |
@JKennedy24 I've been successfully using sqlite-net for quite a while and I still have apps in production that relies on it. I'm very pissed by this ignoring attitude @praeclarum is having towards this project, which we still love very much (and we thanks him a lot). That said, I decided to switch to EF Core in a new project of mine I'm developing. This project is a Xamarin Native which for now runs just on iOS. I have 0 problems with EF core, and besides all: it supports migrations out of the box. I know it pretty well as I've been using EF core on my ASP NET Core backends for quite a while now so really a part from installing the SQLite driver (SQLitePclRaw) everything was pretty natural to me. I used this Medium post as a reference: https://medium.com/@yostane/data-persistence-in-xamarin-using-entity-framework-core-e3a58bdee9d1 You also want to read some material about EF core and understand how it works if you never used it before as it is extremely powerful and can derail you to bad performance and whatnot pretty easily. I suggest reading this book: https://www.manning.com/books/entity-framework-core-in-action but bear in mind is for version 2 of EF core, tho very little has changed in terms of getting started. Hope this helps! |
Good point. I think that it would be desirable that someone from @microsoft take a look about this? For some developers migrate the current SQLite.Net to EF could be too expensive, not a real solution at this time. We need to find a final fix that solve this concurrent access issue in the shortest possible time |
No one is blocking you to downgrade unless you're working on tvOS (which needs sqlite-pcl-raw 2.0 hence >= 1.6 of this lib). If you rollback to 1.5 everything works fine @fgiacomelli |
In terms of solving this particular bug you can either downgrade as @diegostamigni says. Or use this workaround: #881 (comment). Both work. I like the workaround more as it is a bit more defensive against future breaks. In terms of Microsoft or anyone else taking over maintaining this code. It's more general and looking towards the future. My thoughts are more about when the underlying SqliteRaw libraries change (which they already have to V2 and is only supported by the pre release version of this package), someone needs to update and maintain this code |
Thank you @diegostamigni, my concern is about other bugs that we can face downgrading to that version: me and other persons in my team remember that some times ago there was a certain number of different problems that was solved with latest commits |
Yeah, all true @JKennedy24 and makes sense to me.
As a personal advice @fgiacomelli, I went thru and update my codebase to support #881 (comment) and I have no problem whatsoever. I was also forced to update in order to support my app to run on tvOS so I was really into finding a proper solution. So far so good for me. No issues, been on prod on 4 different platforms for months now. |
Hi... I think I solved the problem. I forked the project this morning and made some changes.
Still to be done: If you are interested in giving it a try, any feedback is welcome. |
Ok, I just issued a merge request... let's see... |
Hi everyone, sorry for this trouble. I will investigate today. We have unit tests for async, but I guess they're not good enough. |
@pasteusernamehere No, a breaking change was not intended. Stability is the most important aspect of this library for me. This was a mistake. I'm sorry it's taken this long for this thread to come to my attention. |
@fgiacomelli Would you mind opening a new issue for the "SQLiteException: file is not a database |
@praeclarum Suggestion: I did re-engeneer a lot of things before I touched something that made the bug go away. I have the feeling that the problem lies in the fact that you use lock() and unlock() only if the database is NOT in "full mutex" mode. |
I just opened an issue #955 |
Sorry for the late feedback but we have now tested the new version and the issue appears to be resolved. Please feel free to close this issue whenever you want. Cheers and thanks again for your efforts. |
Great to hear @pasteusernamehere @csm101 Thank you for the analysis. I'll take another look at it with the next update. |
First off, thanks to all the contributors on this project, your effort is greatly appreciated!
Prior to release v1.6.292 I could initiate multiple tasks with db operations and await them all and be guaranteed that each operation would in turn create and commit their own transaction. Tasks would not run simultaneously. It is also worth noting that I am using the default open flags: FullMutex | ReadWrite | Create.
In version 1.5.231 the SkipLock flag was set to true for read operations only. Write operations would then perform a thread lock when performing write operations. This guaranteed that the write operation was the only thread able to start a transaction.
In version 1.6.292 the SkipLock flag is set to true for both read and write operations. When multiple async operations are in play the lock has been changed to use the FakeLockWrapper which does not employ any thread locking. Threads are free to continue down the pipeline to try an initiate a transaction via the write operation.
BeginTransaction uses an Interlocked.CompareExchange to ensure that only one thread can start a transaction. This is good as we only want one transaction at a time, the problem is that if the CompareExchange comparison is not true the code immediately throws an exception (Cannot begin a transaction while already in a transaction). This could be potentially fixed using a semiphore locking mechanism but this also could introduce other issues that I am not aware of. The code could also be fixed by going back to the old locking mechanism employed in v.1.5.231.
Was this behavior change intended? Are consumers now expected to employ their own locking semantics to ensure tasks are queued for execution?
I have attached a small console application that reproduces the issue.
Cheers,
Scott
Code summary:
SQLiteLockFail.zip
The text was updated successfully, but these errors were encountered: