question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

IOException occured when running transaction concurrently(v5)

See original GitHub issue

Overview

when testing litedb-5-beta with concurrent transaction, System.IO.IOException was occured.

Environment

  • dotnet-sdk-3.0
  • TargetFramework: netcoreapp3.0

Steps to reproduce

  1. create dotnet console project with TargetFramework=netcoreapp3.0
  2. run following program
using System;
using System.Threading.Tasks;
using System.Threading;
using System.Linq;
using System.IO;
using LiteDB;

namespace litedbtest
{
    class EntityA
    {
        public long Id { get; set; }
        public int X { get; set; }
        public string Y { get; set; }
    }
    class LiteDbConflictTest
    {
        static long IdValue = 0;
        public static async Task TestManyThread()
        {
            const int TotalNum = 10000;
            const int TaskNum = 2;
            // ensure using initialized database.
            if (File.Exists("manythread.db"))
            {
                File.Delete("manythread.db");
            }
            if (File.Exists("manythread-log.db"))
            {
                File.Delete("manythread-log.db");
            }
            using (var db = new LiteDB.LiteDatabase("manythread.db"))
            {
                await Task.WhenAll(
                    Enumerable.Range(0, TaskNum).Select(async (idx) =>
                    {
                        // concurrent insert task
                        await Task.Yield();
                        db.BeginTrans();
                        var collection = db.GetCollection<EntityA>("HogeCollection");
                        for (int i = 0; i < TotalNum / TaskNum; i++)
                        {
                            collection.Insert(new EntityA()
                            {
                                Id = Interlocked.Increment(ref IdValue),
                                X = idx * 10000 + i,
                                Y = $"{idx}_{i}"
                            });
                        }
                        db.Commit();
                    })
                ).ConfigureAwait(false);
            }
        }
        static void Main(string[] args)
        {
            TestManyThread().Wait();
        }
    }
}

Expected result

the litedb database file named “manythread.db” which has 10000 records.

Actual result

following exception was thrown and exited abnormally.

Unhandled exception. System.AggregateException: One or more errors occurred. (The process cannot access the file 'G:\src\gitrepos\dotnet-sandbox\litedbtest\litedbtest\manythread.db' because it is being used by another process.)
 ---> System.IO.IOException: The process cannot access the file 'G:\src\gitrepos\dotnet-sandbox\litedbtest\litedbtest\manythread.db' because it is being used by another process.
   at System.IO.FileStream.ValidateFileHandle(SafeFileHandle fileHandle)
   at System.IO.FileStream.CreateFileOpenHandle(FileMode mode, FileShare share, FileOptions options)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
   at LiteDB.Engine.FileStreamFactory.GetStream(Boolean canWrite, Boolean sequencial)
   at LiteDB.Engine.StreamPool.<>c__DisplayClass3_0.<.ctor>b__0()
   at System.Lazy`1.PublicationOnlyViaFactory(LazyHelper initializer)
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.get_Value()
   at LiteDB.Engine.StreamPool.get_Writer()
   at LiteDB.Engine.DiskService..ctor(EngineSettings settings)
   at LiteDB.Engine.LiteEngine..ctor(EngineSettings settings)
   at LiteDB.ConnectionString.CreateEngine()
   at System.Lazy`1.PublicationOnlyViaFactory(LazyHelper initializer)
   at System.Lazy`1.CreateValue()
   at litedbtest.LiteDbConflictTest.<>c__DisplayClass1_0.<<TestManyThread>b__0>d.MoveNext() in G:\src\gitrepos\dotnet-sandbox\litedbtest\litedbtest\LiteDbConflictTest.cs:line 39
--- End of stack trace from previous location where exception was thrown ---
   at litedbtest.LiteDbConflictTest.TestManyThread() in G:\src\gitrepos\dotnet-sandbox\litedbtest\litedbtest\LiteDbConflictTest.cs:line 34
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.Wait()
   at litedbtest.Program.Main(String[] args) in G:\src\gitrepos\dotnet-sandbox\litedbtest\litedbtest\Program.cs:line 432

if TaskNum was changed to 1, all records were inserted successfully.

Issue Analytics

  • State:open
  • Created 4 years ago
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
ghostcommented, Jan 17, 2020

@mbdavid when there is a patch release on nuget?

1reaction
mbdavidcommented, Jan 13, 2020

Ok, done. I fix Lazy initialize to thread safe. Thanks again guys

Read more comments on GitHub >

github_iconTop Results From Across the Web

JobEntity [id=*****] was updated by another transaction ...
ExecuteJobsRunnable - exception during job execution: JobEntity [id=852513] was updated by another transaction concurrently org.activiti.engine.
Read more >
Can't commit JPA transaction - RollbackException
Your code is flawed. You are catching an exception, which is never passed to the outside transaction, which still thinks it is ok...
Read more >
OptimisticLockingException caused by Entity was updated ...
Hi, During load we are seeing bunch of OptimisticLockingException and I do understand that this exception is caused when multiple transactions ...
Read more >
Transaction management - Java Reference
Neo4j transaction management, creating unique nodes, and transaction events. ... must be split into several transactions to avoid running out of memory.
Read more >
IBM CICS Asynchronous API: Concurrent Processing Made ...
The RUN TRANSID command initiates a local child transaction that runs asynchronously with the parent transaction. Example 2-1 shows the syntax. Example 2-1 ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found