ClickHouse/src/Common/TransactionID.h

102 lines
3.0 KiB
C++
Raw Normal View History

2021-03-31 17:55:04 +00:00
#pragma once
#include <Core/Types.h>
#include <Core/UUID.h>
2021-04-08 17:20:45 +00:00
#include <fmt/format.h>
#include <IO/WriteHelpers.h>
2021-03-31 17:55:04 +00:00
namespace DB
{
class IDataType;
using DataTypePtr = std::shared_ptr<const IDataType>;
2021-04-08 17:20:45 +00:00
class MergeTreeTransaction;
2021-03-31 17:55:04 +00:00
using CSN = UInt64;
using Snapshot = CSN;
using LocalTID = UInt64;
2021-04-08 17:20:45 +00:00
using TIDHash = UInt64;
2021-03-31 17:55:04 +00:00
2021-12-14 20:06:34 +00:00
namespace Tx
{
const CSN UnknownCSN = 0;
const CSN PrehistoricCSN = 1;
2022-03-14 20:43:34 +00:00
const CSN CommittingCSN = 2;
const CSN MaxReservedCSN = 16;
2021-12-14 20:06:34 +00:00
const LocalTID PrehistoricLocalTID = 1;
2021-12-30 13:15:28 +00:00
const LocalTID DummyLocalTID = 1;
2021-12-14 20:06:34 +00:00
const LocalTID MaxReservedLocalTID = 16;
}
2021-03-31 17:55:04 +00:00
struct TransactionID
{
2022-03-14 20:43:34 +00:00
/// Global sequential number, the newest commit timestamp the we saw when this transaction began
2021-03-31 17:55:04 +00:00
CSN start_csn = 0;
2022-03-14 20:43:34 +00:00
/// Local sequential that is unique for each transaction started by this host within specific start_csn
2021-03-31 17:55:04 +00:00
LocalTID local_tid = 0;
2022-03-14 20:43:34 +00:00
/// UUID of host that has started this transaction
2021-11-08 18:56:09 +00:00
UUID host_id = UUIDHelpers::Nil;
2021-04-08 17:20:45 +00:00
2022-03-14 20:43:34 +00:00
/// NOTE Maybe we could just generate UUIDv4 for each transaction, but it would be harder to debug.
/// Partial order is defined for this TransactionID structure:
/// (tid1.start_csn <= tid2.start_csn) <==> (tid1 <= tid2)
/// (tid1.start_csn == tid2.start_csn && tid1.host_id == tid2.host_id && tid1.local_tid < tid2.local_tid) ==> (tid1 < tid2)
/// If two transaction have the same start_csn, but were started by different hosts, then order is undefined.
2021-04-08 17:20:45 +00:00
bool operator == (const TransactionID & rhs) const
{
return start_csn == rhs.start_csn && local_tid == rhs.local_tid && host_id == rhs.host_id;
}
bool operator != (const TransactionID & rhs) const
{
return !(*this == rhs);
}
2021-12-14 20:06:34 +00:00
TIDHash getHash() const;
bool isEmpty() const
2021-04-08 17:20:45 +00:00
{
2021-12-14 20:06:34 +00:00
assert((local_tid == 0) == (start_csn == 0 && host_id == UUIDHelpers::Nil));
return local_tid == 0;
2021-04-08 17:20:45 +00:00
}
2021-12-14 20:06:34 +00:00
bool isPrehistoric() const
{
assert((local_tid == Tx::PrehistoricLocalTID) == (start_csn == Tx::PrehistoricCSN));
return local_tid == Tx::PrehistoricLocalTID;
}
2021-12-30 13:15:28 +00:00
static void write(const TransactionID & tid, WriteBuffer & buf);
static TransactionID read(ReadBuffer & buf);
2021-03-31 17:55:04 +00:00
};
namespace Tx
{
2021-12-14 20:06:34 +00:00
const TransactionID EmptyTID = {0, 0, UUIDHelpers::Nil};
const TransactionID PrehistoricTID = {PrehistoricCSN, PrehistoricLocalTID, UUIDHelpers::Nil};
2021-12-30 13:15:28 +00:00
const TransactionID DummyTID = {PrehistoricCSN, DummyLocalTID, UUIDHelpers::Nil};
2021-03-31 17:55:04 +00:00
2021-12-14 20:06:34 +00:00
/// So far, that changes will never become visible
const CSN RolledBackCSN = std::numeric_limits<CSN>::max();
2021-03-31 17:55:04 +00:00
}
}
2021-04-08 17:20:45 +00:00
template<>
struct fmt::formatter<DB::TransactionID>
{
template<typename ParseContext>
constexpr auto parse(ParseContext & context)
{
return context.begin();
}
template<typename FormatContext>
auto format(const DB::TransactionID & tid, FormatContext & context)
{
return fmt::format_to(context.out(), "({}, {}, {})", tid.start_csn, tid.local_tid, tid.host_id);
}
};