Click here to Skip to main content
14,022,955 members
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

2.1K views
4 bookmarked
Posted 19 Feb 2019
Licenced CPOL

Cachalot DB - Very Fast Transactional Database for .NET Applications - Part 3

Rate this:
Please Sign up or sign in to vote.
About transactions

Introduction

This is the third part of a series concerning Cachalot DB. The first part can be found here and the second one here.

Two Stage Transactions

The most important thing to understand about two stage transactions is when you really need them.

Most of the time, you don’t.

An operation that involves one single object (Put, TryAdd, UpdateIf, Delete) is always transactional.

It is durable (operations are synchronously written to an append-only transaction log), and it is atomic. An object will be visible to the rest of the world only fully updated or fully inserted.

On a single-node cluster, operations on multiple objects (PutMany, DeleteMany) are also transactional.

You need two stage transactions only if you must transactionally manipulate multiple objects on a multi-node cluster.

As usual, let’s build a small example: a toy banking system that allows money to be transferred between accounts. There are two types of business objects: Account and AccountOperation.

public class Account
{
   [PrimaryKey(KeyDataType.IntKey)]
   public int Id { get; set; }

   [Index(KeyDataType.IntKey, true)]
   public decimal Balance { get; set; }
}

public class AccountOperation
{
   [PrimaryKey(KeyDataType.IntKey)]
   public int Id { get; set; }

   [Index(KeyDataType.IntKey)]
   public int SourceAccount { get; set; }

   [Index(KeyDataType.IntKey)]
   public int TargetAccount { get; set; }

   [Index(KeyDataType.IntKey, ordered:true)]
   public DateTime Timestamp { get; set; }

   public decimal TransferedAmount { get; set; }
}

Let’s create two accounts. No need for transactions at this stage.

var accountIds = connector.GenerateUniqueIds("account_id", 2);
var accounts = connector.DataSource<Account>();

var account1 = new Account {Id = accountIds[0], Balance = 100};
var account2 = new Account {Id = accountIds[1], Balance = 100};

accounts.Put(account1);
accounts.Put(account2);

When we transfer money between the accounts, we would like to simultaneously (atomically) update the balance of both accounts and to create a new instance of AccountOperation.

This is how the business logic could be implemented:

private static void MoneyTransfer
(Connector connector, Account sourceAccount, Account targetAccount, decimal amount)
{
    sourceAccount.Balance -= amount;
    targetAccount.Balance += amount;

    var tids = connector.GenerateUniqueIds("transaction_id", 1);
    var transfer = new AccountOperation
    {
        Id = tids[0],
        SourceAccount = sourceAccount.Id,
        TargetAccount = targetAccount.Id,
        TransferedAmount = amount
    };
    var transaction = connector.BeginTransaction();
    transaction.Put(sourceAccount);
    transaction.Put(targetAccount);
    transaction.Put(transfer);
    // this is where the two stage transaction happens
    transaction.Commit();
}

The operations allowed inside a transaction are:

  • Put
  • Delete
  • UpdateIf

If a conditional update (UpdateIf) is used and the condition is not satisfied by one object, the whole transaction is rolled back.

In-Process Server

In some cases, especially if the quantity of data is bounded and it can be stored on a single node, you can instantiate a Cachalot server directly inside your server process. This will give blazing fast responses as there is no more network latency involved.

In order to do this, pass an empty client configuration to the Connector constructor. A database server will be instantiated inside the connector object and communications will be done by simple in-process calls, not a TCP channel.

var connector = new Connector(new ClientConfig());

Connector implements IDisposable. Disposing the Connector will graciously stop the server. You need to instantiate the Connector once when the server process starts and dispose it once when the server process stops.

The fully open source code is available at:

    https://github.com/usinesoft/Cachalot

Precompiled binaries (including demo clients) and full documentation are available at:

    https://github.com/usinesoft/Cachalot/releases/latest

The client code is available as nuget package at nuget.org.

To install: Install-Package Cachalot.Client

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

No Biography provided

You may also be interested in...

Comments and Discussions

 
Questioncorrections Pin
Nelek19-Feb-19 1:18
protectorNelek19-Feb-19 1:18 
AnswerRe: corrections Pin
Dan Ionescu (USINESOFT)19-Feb-19 23:24
memberDan Ionescu (USINESOFT)19-Feb-19 23:24 
GeneralRe: corrections Pin
Nelek20-Feb-19 0:06
protectorNelek20-Feb-19 0:06 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web02 | 2.8.190417.4 | Last Updated 19 Feb 2019
Article Copyright 2019 by Dan Ionescu (USINESOFT)
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid