[BUG] LiteDatabase is not thread safe
See original GitHub issueVersion LiteDB 5.0.2 with .NET Core 3.1 (don’t think this part matters)
Describe the bug Per the suggestion at https://github.com/mbdavid/LiteDB/wiki/Concurrency, I create a single LiteDatabase instance to share with multiple thread. The code snippet inserts a single record then queue a Task to remove the record. Even though the deletion Tasks are running on a separate thread, the Tasks are chained so only one deletion is running at a time. At the end of the program, the code output 0 items. When using LiteDB Studio to view the database, there are still records in the table. The number of left-over records are random.
Code to Reproduce
class Program
{
private static LiteDatabase _db;
private static Task _eventProcessingTask;
private static readonly object _processingTaskLock = new object();
private static string _tableName = "myTable";
static void Main(string[] args)
{
_db = new LiteDatabase($"Filename=MyDb;Mode=Exclusive;Async=false;Flush=true;");
for (int i = 1; i < 1000; i++)
{
Insert(i);
}
System.Threading.Thread.Sleep(5000);
var table = _db.GetCollection<TableRow>(_tableName);
Console.WriteLine($"There are {table.Count()} items.");
}
static void Insert(int id)
{
var table = _db.GetCollection<TableRow>(_tableName);
table.Insert(new TableRow { Id = id, Data = $"item {id}"});
lock (_processingTaskLock)
{
if (_eventProcessingTask == null)
_eventProcessingTask = Task.Run(() => Delete(id));
else
_eventProcessingTask = _eventProcessingTask.ContinueWith((t) => Delete(id));
}
}
static void Delete(int id)
{
var table = _db.GetCollection<TableRow>(_tableName);
table.Delete(new BsonValue(id));
}
}
public class TableRow
{
public int Id { get; set; }
public string Data { get; set; }
}
Expected behavior In-memory count should show the count of the items of the database in the file system.
Issue Analytics
- State:
- Created 4 years ago
- Comments:8 (4 by maintainers)
Top Results From Across the Web
[QUESTION] Is LiteDB v5 is thread-safe for multiple reader ...
I'm using LiteDB for per-process cache to caching complex queries results from external database. It works well basically except accessing ...
Read more >LiteDB Deadlocks - I may be using LiteDB wrong
Since LiteDB is supposed to be thread-safe, I don't use locks to synchronize reads/writes to the DB. I've made a test (on a...
Read more >LiteDB :: A .NET embedded NoSQL database
Thread-safe with cross collection transaction ; No locks for readers. Per collection writer locks; Partial document lookup/loader and index-only queries ...
Read more >LiteDB
LiteDB - A .NET NoSQL Document Store in a single data file · Serverless NoSQL Document Store · Simple API, similar to MongoDB...
Read more >LiteDB - A .NET embedded NoSQL database
As initially said it is no problem if you have multiple things accessing the database at the same time as it thread-safe. That...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Hi @Thdm1907, there is some points here:
Engine contains an async writer queue to write in disk (in async thread) all dirty pages direct to Log file. This process still occurs after user get “Insert OK” (or delete, update…). If you interrupt your program during this async write, this missing pages/transactions will not be write and when open database again you will see “half” operations.
When you call
Dispose
fromLiteDatabase
, this method waits for this async thread finish before close database, runs Checkpoint operation (coping LOG file into datafile) before everything finish. So, with noDispose
, you can get some “random” data inside database. Maybe is the case for you.Yes, sorry, it was late on night and wasn’t thinking properly. I’m building a repro app to attach to the issue.