mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 16:43:03 +01:00
Hopefully final corrections: missed (info, EDS) items, spaces, etc
This commit is contained in:
parent
3fcc02105f
commit
f8752bb677
@ -128,7 +128,7 @@ So, there are three kinds of read-committed transactions now:
|
||||
When statement executed within read committed read consistency transaction its database view is
|
||||
not changed (similar to snapshot transaction). Therefore it is useless to wait for commit of
|
||||
concurrent transaction in the hope to re-read new committed record version. On read, behavior is
|
||||
similar to read committed *no record version* transaction - do not wait for active transaction and
|
||||
similar to read committed *record version* transaction - do not wait for active transaction and
|
||||
walk backversions chain looking for record version visible to the current snapshot.
|
||||
|
||||
When update conflict happens engine behavior is changed. If concurrent transaction is active,
|
||||
|
@ -499,7 +499,7 @@ public:
|
||||
StmtNumber generateStatementId();
|
||||
// void assignLatestTransactionId(TraNumber number);
|
||||
void assignLatestAttachmentId(AttNumber number);
|
||||
|
||||
|
||||
|
||||
USHORT getMaxIndexKeyLength() const
|
||||
{
|
||||
|
@ -1471,6 +1471,11 @@ void Transaction::generateTPB(thread_db* /*tdbb*/, ClumpletWriter& tpb,
|
||||
tpb.insertTag(isc_tpb_rec_version);
|
||||
break;
|
||||
|
||||
case traReadCommitedReadConsistency:
|
||||
tpb.insertTag(isc_tpb_read_committed);
|
||||
tpb.insertTag(isc_tpb_read_consistency);
|
||||
break;
|
||||
|
||||
case traConcurrency:
|
||||
tpb.insertTag(isc_tpb_concurrency);
|
||||
break;
|
||||
@ -1574,7 +1579,9 @@ Transaction* Transaction::getTransaction(thread_db* tdbb, Connection* conn, TraS
|
||||
TraModes traMode = traConcurrency;
|
||||
if (tran->tra_flags & TRA_read_committed)
|
||||
{
|
||||
if (tran->tra_flags & TRA_rec_version)
|
||||
if (tran->tra_flags & TRA_read_consistency)
|
||||
traMode = traReadCommitedReadConsistency;
|
||||
else if (tran->tra_flags & TRA_rec_version)
|
||||
traMode = traReadCommitedRecVersions;
|
||||
else
|
||||
traMode = traReadCommited;
|
||||
|
@ -47,7 +47,8 @@ class Transaction;
|
||||
class Statement;
|
||||
class Blob;
|
||||
|
||||
enum TraModes {traReadCommited, traReadCommitedRecVersions, traConcurrency, traConsistency};
|
||||
enum TraModes {traReadCommited, traReadCommitedRecVersions, traReadCommitedReadConsistency,
|
||||
traConcurrency, traConsistency};
|
||||
enum TraScope {traNotSet = 0, traAutonomous, traCommon, traTwoPhase};
|
||||
|
||||
// Known built-in provider's names
|
||||
|
@ -1114,7 +1114,9 @@ void INF_transaction_info(const jrd_tra* transaction,
|
||||
if (transaction->tra_flags & TRA_read_committed)
|
||||
{
|
||||
*p++ = isc_info_tra_read_committed;
|
||||
if (transaction->tra_flags & TRA_rec_version)
|
||||
if (transaction->tra_flags & TRA_read_consistency)
|
||||
*p++ = isc_info_tra_read_consistency;
|
||||
else if (transaction->tra_flags & TRA_rec_version)
|
||||
*p++ = isc_info_tra_rec_version;
|
||||
else
|
||||
*p++ = isc_info_tra_no_rec_version;
|
||||
|
@ -401,6 +401,7 @@ enum info_db_provider
|
||||
// isc_info_tra_read_committed options
|
||||
#define isc_info_tra_no_rec_version 0
|
||||
#define isc_info_tra_rec_version 1
|
||||
#define isc_info_tra_read_consistency 2
|
||||
|
||||
// isc_info_tra_access responses
|
||||
#define isc_info_tra_readonly 0
|
||||
|
@ -295,7 +295,7 @@ void TipCache::loadInventoryPages(thread_db* tdbb)
|
||||
// At the same time, simple write to a volatile variable is not good
|
||||
// as it is not deterministic. Some compilers generate barriers and some do not.
|
||||
((std::atomic<CommitNumber>*)(statusBlock->data + transOffset))->store(cn, std::memory_order_relaxed);
|
||||
|
||||
|
||||
if (++t > hdr_next_transaction)
|
||||
break;
|
||||
|
||||
@ -431,7 +431,7 @@ TraNumber TipCache::findStates(TraNumber minNumber, TraNumber maxNumber, ULONG m
|
||||
// Barrier is not needed here. Slightly out-dated information shall be ok here.
|
||||
// Such transaction shall already be considered active by our caller.
|
||||
// TODO: check if this assumption is indeed correct.
|
||||
|
||||
|
||||
CommitNumber cn = ((std::atomic<CommitNumber>*)(statusBlock->data + transOffset))->load(std::memory_order_relaxed);
|
||||
switch (cn)
|
||||
{
|
||||
|
@ -151,7 +151,7 @@ void TRA_setup_request_snapshot(Jrd::thread_db* tdbb, Jrd::jrd_req* request)
|
||||
// We assume that request is already attached to a transaction
|
||||
fb_assert(transaction);
|
||||
|
||||
// If we are not READ COMMITTED or stable cursors are not needed then nothing to do here
|
||||
// If we are not READ COMMITTED or read consistency is not needed then nothing to do here
|
||||
if (!(transaction->tra_flags & TRA_read_committed) || !(transaction->tra_flags & TRA_read_consistency))
|
||||
return;
|
||||
|
||||
@ -1521,7 +1521,7 @@ void TRA_set_state(thread_db* tdbb, jrd_tra* transaction, TraNumber number, int
|
||||
}
|
||||
|
||||
|
||||
int TRA_snapshot_state(thread_db* tdbb, jrd_tra* trans, TraNumber number, CommitNumber *snapshot)
|
||||
int TRA_snapshot_state(thread_db* tdbb, const jrd_tra* trans, TraNumber number, CommitNumber *snapshot)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -1552,7 +1552,7 @@ int TRA_snapshot_state(thread_db* tdbb, jrd_tra* trans, TraNumber number, Commit
|
||||
// If the transaction is older than the oldest
|
||||
// interesting transaction, it must be committed.
|
||||
|
||||
if (number < trans->tra_oldest)
|
||||
if (number < trans->tra_oldest)
|
||||
{
|
||||
if (snapshot)
|
||||
*snapshot = att->att_active_snapshots.getSnapshotForVersion(CN_PREHISTORIC);
|
||||
@ -1561,7 +1561,7 @@ int TRA_snapshot_state(thread_db* tdbb, jrd_tra* trans, TraNumber number, Commit
|
||||
|
||||
// If the transaction is the system transaction, it is considered committed.
|
||||
|
||||
if (number == TRA_system_transaction)
|
||||
if (number == TRA_system_transaction)
|
||||
{
|
||||
if (snapshot)
|
||||
*snapshot = att->att_active_snapshots.getSnapshotForVersion(CN_PREHISTORIC);
|
||||
@ -2711,7 +2711,7 @@ static void transaction_options(thread_db* tdbb,
|
||||
RelationLockTypeMap lockmap;
|
||||
|
||||
TriState wait, lock_timeout;
|
||||
TriState isolation, read_only, rec_version;
|
||||
TriState isolation, read_only, rec_version, read_consistency;
|
||||
bool anylock_write = false;
|
||||
|
||||
++tpb;
|
||||
@ -2793,6 +2793,14 @@ static void transaction_options(thread_db* tdbb,
|
||||
Arg::Gds(isc_tpb_multiple_spec) << Arg::Str("isc_tpb_rec_version"));
|
||||
}
|
||||
|
||||
if (read_consistency.isAssigned())
|
||||
{
|
||||
ERR_post(Arg::Gds(isc_bad_tpb_content) <<
|
||||
// 'Option @1 is not valid if @2 was used previously in TPB'
|
||||
Arg::Gds(isc_tpb_conflicting_options) <<
|
||||
Arg::Str("isc_tpb_rec_version") << Arg::Str("isc_tpb_read_consistency"));
|
||||
}
|
||||
|
||||
transaction->tra_flags &= ~TRA_read_consistency;
|
||||
transaction->tra_flags |= TRA_rec_version;
|
||||
break;
|
||||
@ -2810,8 +2818,15 @@ static void transaction_options(thread_db* tdbb,
|
||||
Arg::Gds(isc_tpb_multiple_spec) << Arg::Str("isc_tpb_no_rec_version"));
|
||||
}
|
||||
|
||||
if (read_consistency.isAssigned())
|
||||
{
|
||||
ERR_post(Arg::Gds(isc_bad_tpb_content) <<
|
||||
// 'Option @1 is not valid if @2 was used previously in TPB'
|
||||
Arg::Gds(isc_tpb_conflicting_options) <<
|
||||
Arg::Str("isc_tpb_no_rec_version") << Arg::Str("isc_tpb_read_consistency"));
|
||||
}
|
||||
|
||||
transaction->tra_flags &= ~(TRA_rec_version | TRA_read_consistency);
|
||||
;
|
||||
break;
|
||||
|
||||
case isc_tpb_read_consistency:
|
||||
@ -2821,14 +2836,22 @@ static void transaction_options(thread_db* tdbb,
|
||||
Arg::Gds(isc_tpb_option_without_rc) << Arg::Str("isc_tpb_read_consistency"));
|
||||
}
|
||||
|
||||
if (!rec_version.assignOnce(false))
|
||||
if (!read_consistency.assignOnce(true))
|
||||
{
|
||||
ERR_post(Arg::Gds(isc_bad_tpb_content) <<
|
||||
Arg::Gds(isc_tpb_multiple_spec) << Arg::Str("isc_tpb_read_consistency"));
|
||||
}
|
||||
|
||||
transaction->tra_flags &= ~TRA_rec_version;
|
||||
transaction->tra_flags |= TRA_read_consistency;
|
||||
if (rec_version.isAssigned())
|
||||
{
|
||||
ERR_post(Arg::Gds(isc_bad_tpb_content) <<
|
||||
// 'Option @1 is not valid if @2 was used previously in TPB'
|
||||
Arg::Gds(isc_tpb_conflicting_options) <<
|
||||
Arg::Str("isc_tpb_read_consistency") << (rec_version.asBool() ?
|
||||
Arg::Str("isc_tpb_rec_version") : Arg::Str("isc_tpb_no_rec_version")) );
|
||||
}
|
||||
|
||||
transaction->tra_flags |= TRA_read_consistency | TRA_rec_version;
|
||||
break;
|
||||
|
||||
case isc_tpb_nowait:
|
||||
|
@ -411,11 +411,11 @@ const ULONG TRA_restart_requests = 0x4000L; // restart all requests in attachmen
|
||||
const ULONG TRA_no_auto_undo = 0x8000L; // don't start a savepoint in TRA_start
|
||||
const ULONG TRA_precommitted = 0x10000L; // transaction committed at startup
|
||||
const ULONG TRA_own_interface = 0x20000L; // tra_interface was created for internal needs
|
||||
const ULONG TRA_read_consistency = 0x40000L; // ensure read consistency for cursors in this transaction
|
||||
const ULONG TRA_read_consistency = 0x40000L; // ensure read consistency in this transaction
|
||||
|
||||
// flags derived from TPB, see also transaction_options() at tra.cpp
|
||||
const ULONG TRA_OPTIONS_MASK = (TRA_degree3 | TRA_readonly | TRA_ignore_limbo | TRA_read_committed |
|
||||
TRA_autocommit | TRA_rec_version | TRA_no_auto_undo | TRA_restart_requests);
|
||||
TRA_autocommit | TRA_rec_version | TRA_read_consistency | TRA_no_auto_undo | TRA_restart_requests);
|
||||
|
||||
const int TRA_MASK = 3;
|
||||
//const int TRA_BITS_PER_TRANS = 2;
|
||||
|
@ -54,7 +54,7 @@ Jrd::jrd_tra* TRA_reconnect(Jrd::thread_db* tdbb, const UCHAR*, USHORT);
|
||||
void TRA_release_transaction(Jrd::thread_db* tdbb, Jrd::jrd_tra*, Jrd::TraceTransactionEnd*);
|
||||
void TRA_rollback(Jrd::thread_db* tdbb, Jrd::jrd_tra*, const bool, const bool);
|
||||
void TRA_set_state(Jrd::thread_db* tdbb, Jrd::jrd_tra* transaction, TraNumber number, int state);
|
||||
int TRA_snapshot_state(Jrd::thread_db* tdbb, Jrd::jrd_tra* trans, TraNumber number, CommitNumber* snapshot = NULL);
|
||||
int TRA_snapshot_state(Jrd::thread_db* tdbb, const Jrd::jrd_tra* trans, TraNumber number, CommitNumber* snapshot = NULL);
|
||||
Jrd::jrd_tra* TRA_start(Jrd::thread_db* tdbb, ULONG flags, SSHORT lock_timeout, Jrd::jrd_tra* outer = NULL);
|
||||
Jrd::jrd_tra* TRA_start(Jrd::thread_db* tdbb, int, const UCHAR*, Jrd::jrd_tra* outer = NULL);
|
||||
int TRA_state(const UCHAR*, TraNumber oldest, TraNumber number);
|
||||
|
@ -5218,7 +5218,7 @@ static void list_staying(thread_db* tdbb, record_param* rpb, RecordStack& stayin
|
||||
RuntimeStatistics::Accumulator backversions(tdbb, rpb->rpb_relation,
|
||||
RuntimeStatistics::RECORD_BACKVERSION_READS);
|
||||
|
||||
|
||||
|
||||
// Limit number of "restarts" if primary version constantly changed. Currently,
|
||||
// LS_ACTIVE_RPB is passed by VIO_intermediate_gc only and it is ok to return
|
||||
// empty staying in this case.
|
||||
@ -5677,7 +5677,7 @@ static int prepare_update( thread_db* tdbb,
|
||||
temp->rpb_b_page = rpb->rpb_b_page;
|
||||
temp->rpb_b_line = rpb->rpb_b_line;
|
||||
temp->rpb_flags &= ~rpb_delta;
|
||||
temp->rpb_flags |= rpb->rpb_flags & rpb_delta; // NS 2014-09-10: XXX - what is this code doing?
|
||||
temp->rpb_flags |= rpb->rpb_flags & rpb_delta;
|
||||
temp->rpb_transaction_nr = rpb->rpb_transaction_nr;
|
||||
|
||||
DPM_store(tdbb, temp, stack, DPM_secondary);
|
||||
@ -5730,7 +5730,7 @@ static int prepare_update( thread_db* tdbb,
|
||||
switch (state)
|
||||
{
|
||||
case tra_committed:
|
||||
// We need to loop waiting in read committed transactions only
|
||||
// We need to loop waiting in read committed with no read consistency transactions only
|
||||
if (!(transaction->tra_flags & TRA_read_committed) ||
|
||||
(transaction->tra_flags & TRA_read_consistency))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user