Skip to content

EnlistInAmbientTransaction should not change isolation level to SERIALIZABLE if there is no ambient transaction #12

Closed

Description

@fschmied

When EnlistInAmbientTransaction is called in wire-up, the default isolation level of the SQL Persistence for SQL Server is changed from the database default of READ COMMITTED to SERIALIZABLE. This can and probably should be fixed directly in NEventStore (NEventStore/NEventStore#414), but if it isn't, a workaround should be added in NEventStore.Persistence.SQL because the SQL persistence doesn't work as nicely with the SERIALIZABLE isolation level (we experienced database-level deadlocks with multiple readers/writers), and it's also much less efficient.

Reason for the SERIALIZABLE isolation level: If the TransactionScopeOption.Required is used (via code in PersistenceWireup) without specifying an isolation level, the TransactionScope default isolation level of SERIALIZABLE is used if there is no ambient transaction.

Activity

  1. fschmied commented on Mar 23, 2016

    @fschmied
    Author

    Workaround for 5.2.0: Ensure there is an active TransactionScope with ReadCommitted isolation level whenever an NEventStore API is called and EnlistInAmbientTransaction is turned on.

  2. HAXEN commented on May 11, 2016

    @HAXEN

    @fschmied Could you provide a simple code example of how this should be done? For me as a novice to understand.

  3. fschmied commented on May 30, 2016

    @fschmied
    Author

    @HAXEN Sorry, I missed your question. First, check if you really need EnlistInAmbientTransaction, many CQRS applications will not need this option. If you do, wrap all your calls to IStoreEvents in blocks such as this one:

    using (var tx = new TransactionScope (TransactionScopeOption.Required, IsolationLevel.ReadCommitted))
    {
      var stream = _eventStore.OpenStream(bucketId, streamId, fromRevision, int.MaxValue);
      tx.Complete();
      return stream;
    }
    
  4. fschmied commented on May 30, 2016

    @fschmied
    Author

    (PS: IPersistStreams might also be affected, you'll need to check this yourself.)

  5. HAXEN commented on May 30, 2016

    @HAXEN

    My usecase being:

    Let's say I have an AggregateRoot representing a country and the key being
    'sv' for sweden and 'fr' for france etc...

    In order to not having duplicates into the eventstore I figure either
    having the streamId = 'sv' and query that before creating a new, or having
    a table languages with a primary key on countrycode.

    Or

    Should I make the system being able to create duplicates and in that case
    having the read side "delete" the duplicate with a command? In this case
    how is this usually handled regarding feedback to the user?

    Being sort of new to CQRS this is not clear to me.

    On Mon, May 30, 2016 at 4:47 PM, Fabian Schmied notifications@github.com
    wrote:

    (PS: IPersistStreams might also be affected, you'll need to check this
    yourself.)

    —
    You are receiving this because you were mentioned.
    Reply to this email directly, view it on GitHub
    #12 (comment),
    or mute the thread
    https://github.com/notifications/unsubscribe/AAJZ1nXVIHqtk4JqiNeG1bUfrQu2FTe0ks5qGviLgaJpZM4FvBfm
    .

  6. fschmied commented on Jun 2, 2016

    @fschmied
    Author

    @HAXEN I guess this bug report is not the right way to discuss your specific question, better ask at https://groups.google.com/d/forum/dddcqrs for CQRS-speciifc questions or at https://groups.google.com/forum/#!forum/neventstore for NEventStore-related ones.

    That said, the OpenStream API in NEventStore allows you to specify "0" as the "minimum revision" when opening a stream. This will create the stream if it doesn't exist, or read it if it does. You can then check whether the StreamRevision is 0. If it is, the stream has just been newly created. If not, it already existed. This should make it quite easy to prevent duplicates based on the stream ID.

  7. AGiorgetti commented on Apr 8, 2017

    @AGiorgetti
    Member

    If there's no ambiente transaction an 'EnlistInAmbientTransaction' has been called a new TransactionScope with the default ReadCommitted transaction isolation level will be generated

  8. added a commit that references this issue on Apr 8, 2017
    6a0f9ee
  9. added this to the v6.0.0 milestone on Apr 8, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions