Using an RDBMS as event sourcing storage

前端 未结 6 1677
灰色年华
灰色年华 2020-12-07 07:02

If I were using an RDBMS (e.g. SQL Server) to store event sourcing data, what might the schema look like?

I\'ve seen a few variations talked about in an abstract sens

6条回答
  •  日久生厌
    2020-12-07 07:42

    I think solution (1 & 2) can become a problem very quickly as your domain model evolves. New fields are created, some change meaning, and some can become no longer used. Eventually your table will have dozens of nullable fields, and loading the events will be mess.

    Also, remember that the event store should be used only for writes, you only query it to load the events, not the properties of the aggregate. They are separate things (that is the essence of CQRS).

    Solution 3 what people usually do, there are many ways to acomplish that.

    As example, EventFlow CQRS when used with SQL Server creates a table with this schema:

    CREATE TABLE [dbo].[EventFlow](
        [GlobalSequenceNumber] [bigint] IDENTITY(1,1) NOT NULL,
        [BatchId] [uniqueidentifier] NOT NULL,
        [AggregateId] [nvarchar](255) NOT NULL,
        [AggregateName] [nvarchar](255) NOT NULL,
        [Data] [nvarchar](max) NOT NULL,
        [Metadata] [nvarchar](max) NOT NULL,
        [AggregateSequenceNumber] [int] NOT NULL,
     CONSTRAINT [PK_EventFlow] PRIMARY KEY CLUSTERED 
    (
        [GlobalSequenceNumber] ASC
    )
    

    where:

    • GlobalSequenceNumber: Simple global identification, may be used for ordering or identifying the missing events when you create your projection (readmodel).
    • BatchId: An identification of the group of events that where inserted atomically (TBH, have no idea why this would be usefull)
    • AggregateId: Identification of the aggregate
    • Data: Serialized event
    • Metadata: Other usefull information from event (e.g. event type used for deserialize, timestamp, originator id from command, etc.)
    • AggregateSequenceNumber: Sequence number within the same aggregate (this is usefull if you cannot have writes happening out of order, so you use this field to for optimistic concurrency)

    However, if you are creating from scratch I would recomend following the YAGNI principle, and creating with the minimal required fields for your use case.

提交回复
热议问题