beedb/include/concurrency/transaction_manager.h

170 lines
7.0 KiB
C++

/*------------------------------------------------------------------------------*
* Architecture & Implementation of DBMS *
*------------------------------------------------------------------------------*
* Copyright 2022 Databases and Information Systems Group TU Dortmund *
* Visit us at *
* http://dbis.cs.tu-dortmund.de/cms/en/home/ *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* Authors: *
* Maximilian Berens <maximilian.berens@tu-dortmund.de> *
* Roland Kühn <roland.kuehn@cs.tu-dortmund.de> *
* Jan Mühlig <jan.muehlig@tu-dortmund.de> *
*------------------------------------------------------------------------------*
*/
#pragma once
#include "metadata.h"
#include "transaction.h"
#include <array>
#include <atomic>
#include <buffer/manager.h>
#include <shared_mutex>
#include <unordered_map>
namespace beedb::concurrency
{
/**
* The TransactionManager creates new transactions and performs
* commit and abort of those transactions.
*/
class TransactionManager
{
public:
explicit TransactionManager(buffer::Manager &buffer_manager);
~TransactionManager();
/**
* Creates a new transaction with the given isolation level.
*
* @param isolation_level Isolation level.
* @return New transaction.
*/
Transaction *new_transaction(const IsolationLevel isolation_level = IsolationLevel::Serializable);
/**
* Aborts the given transaction and reverts all
* writes done by this transaction.
* @param transaction Transaction to abort.
*/
void abort(Transaction &transaction);
/**
* Commits a transaction. Before writing the data written by the transaction
* to the global state, the transaction is validated.
* @param transaction Transaction to commit.
* @return True, when the commit was successful. Otherwise, the transaction
* will be aborted automatically.
*/
bool commit(Transaction &transaction);
/**
* Tests if a given timestamp range is visible for the given transaction.
* @param transaction Transaction to test.
* @param begin_timestamp Start timestamp.
* @param end_timestamp End timestamp.
* @return True, when the transaction is allowed to see the data living in the given range.
*/
static bool is_visible(const Transaction &transaction, const timestamp begin_timestamp,
const timestamp end_timestamp);
/**
* Tests if a given metadata is visible for the given transaction.
* @param transaction Transaction to test.
* @param metadata Metadata of a record.
* @return True, when the transaction is allowed to see the data living in the given range.
*/
static bool is_visible(const Transaction &transaction, Metadata *const metadata)
{
return is_visible(transaction, metadata->begin_timestamp(), metadata->end_timestamp());
}
/**
* @return The next timestamp for transactions.
*/
timestamp::timestamp_t next_timestamp() const
{
return _next_timestamp.load();
}
/**
* Updates the next timestamp for transactions.
* @param timestamp Next timestamp for the next transaction.
*/
void next_timestamp(const timestamp::timestamp_t timestamp)
{
_next_timestamp.store(timestamp);
}
private:
// Buffer manager to read/write to pages.
buffer::Manager &_buffer_manager;
// Timestamp for the next transaction.
std::atomic<timestamp::timestamp_t> _next_timestamp{2u};
// Map of Timestamp => Transaction of only committed transactions.
std::unordered_map<timestamp::timestamp_t, Transaction *> _commit_history;
// Latch for the history map.
std::shared_mutex _commit_history_latch;
/**
* Validates a transaction to commit.
* @param transaction Transaction to commit.
* @return True, when the transaction is valid.
*/
bool validate(Transaction &transaction);
/**
* Validates write skew anomalies. A write skew anomaly can occur,
* when a transaction T reads a record A and writes a record B,
* but a concurrent transaction T' writes to A between T reading A and
* writing B.
* What the DBMS can not see is how A affects B in T, therefore we have
* to abort the transaction.
* @param transaction Transaction to validate.
* @param concurrent_transactions List of transactions that committed between
* the transactions started and committed.
* @return True, when the transaction is valid.
*/
static bool validate_write_skew_anomalies(Transaction &transaction,
const std::vector<Transaction *> &concurrent_transactions);
/**
* Validates the scan set of a transaction. A transaction T
* may scan a table while a concurrent transaction inserts/deletes/updates
* a record that would be part of the scan. Therefore, the scan
* has to be (re)checked to validate that the scan would be the same
* at commit time.
* @param transaction Transaction to validate.
* @param concurrent_transactions List of concurrent transactions.
* @return True, when the transaction is valid.
*/
bool validate_scan_set(Transaction &transaction, const std::vector<Transaction *> &concurrent_transactions);
/**
* Validates a single scan of a transaction against the write sets of concurrent transactions.
* @param scan_set_item Single scan set.
* @param write_set List of write sets of concurrent transactions.
* @return True, when the scan set is valid.
*/
bool validate_scan_set_item(ScanSetItem *scan_set_item, const std::vector<WriteSetItem> &write_set);
/**
* Calculates the transactions that have committed between begin and end.
* @param begin Begin.
* @param end End.
* @return List of transactions that committed in the given time range.
*/
std::vector<Transaction *> committed_transactions(const timestamp::timestamp_t begin,
const timestamp::timestamp_t end);
};
} // namespace beedb::concurrency