8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 14:03:07 +01:00

Improvement CORE-5434 : Read-only transactions in SuperServer could avoid immediate write of Header and TIP pages after change

This commit is contained in:
hvlad 2017-01-03 18:42:32 +02:00
parent 1a103a273b
commit 23a55f0b45

View File

@ -89,7 +89,7 @@ typedef Firebird::GenericMap<Firebird::Pair<Firebird::NonPooled<USHORT, UCHAR> >
#ifdef SUPERSERVER_V2 #ifdef SUPERSERVER_V2
static TraNumber bump_transaction_id(thread_db*, WIN*); static TraNumber bump_transaction_id(thread_db*, WIN*);
#else #else
static header_page* bump_transaction_id(thread_db*, WIN*); static header_page* bump_transaction_id(thread_db*, WIN*, bool);
#endif #endif
static void retain_context(thread_db* tdbb, jrd_tra* transaction, bool commit, int state); static void retain_context(thread_db* tdbb, jrd_tra* transaction, bool commit, int state);
static void expand_view_lock(thread_db* tdbb, jrd_tra*, jrd_rel*, UCHAR lock_type, static void expand_view_lock(thread_db* tdbb, jrd_tra*, jrd_rel*, UCHAR lock_type,
@ -1445,16 +1445,24 @@ void TRA_set_state(thread_db* tdbb, jrd_tra* transaction, TraNumber number, int
WIN window(DB_PAGE_SPACE, -1); WIN window(DB_PAGE_SPACE, -1);
tx_inv_page* tip = fetch_inventory_page(tdbb, &window, sequence, LCK_write); tx_inv_page* tip = fetch_inventory_page(tdbb, &window, sequence, LCK_write);
UCHAR* address = tip->tip_transactions + byte;
const int old_state = ((*address) >> shift) & TRA_MASK;
#ifdef SUPERSERVER_V2 #ifdef SUPERSERVER_V2
CCH_MARK(tdbb, &window); CCH_MARK(tdbb, &window);
const ULONG generation = tip->tip_header.pag_generation; const ULONG generation = tip->tip_header.pag_generation;
#else #else
CCH_MARK_MUST_WRITE(tdbb, &window); if (!(dbb->dbb_flags & DBB_shared) || transaction->tra_flags & TRA_write ||
old_state != tra_active || state != tra_committed)
{
CCH_MARK_MUST_WRITE(tdbb, &window);
}
else
CCH_MARK(tdbb, &window);
#endif #endif
// set the state on the TIP page // set the state on the TIP page
UCHAR* address = tip->tip_transactions + byte;
*address &= ~(TRA_MASK << shift); *address &= ~(TRA_MASK << shift);
*address |= state << shift; *address |= state << shift;
@ -1944,7 +1952,7 @@ static TraNumber bump_transaction_id(thread_db* tdbb, WIN* window)
#else #else
static header_page* bump_transaction_id(thread_db* tdbb, WIN* window) static header_page* bump_transaction_id(thread_db* tdbb, WIN* window, bool dontWrite)
{ {
/************************************** /**************************************
* *
@ -1999,7 +2007,11 @@ static header_page* bump_transaction_id(thread_db* tdbb, WIN* window)
// Extend, if necessary, has apparently succeeded. Next, update header page // Extend, if necessary, has apparently succeeded. Next, update header page
CCH_MARK_MUST_WRITE(tdbb, window); if (dontWrite && !new_tip)
CCH_MARK(tdbb, window);
else
CCH_MARK_MUST_WRITE(tdbb, window);
dbb->dbb_next_transaction = number; dbb->dbb_next_transaction = number;
Ods::writeNT(header, number); Ods::writeNT(header, number);
@ -2391,7 +2403,10 @@ static void retain_context(thread_db* tdbb, jrd_tra* transaction, bool commit, i
new_number = dbb->dbb_next_transaction + dbb->generateTransactionId(tdbb); new_number = dbb->dbb_next_transaction + dbb->generateTransactionId(tdbb);
else else
{ {
const header_page* const header = bump_transaction_id(tdbb, &window); const bool dontWrite = (dbb->dbb_flags & DBB_shared) &&
(transaction->tra_flags & TRA_readonly);
const header_page* const header = bump_transaction_id(tdbb, &window, dontWrite);
new_number = Ods::getNT(header); new_number = Ods::getNT(header);
} }
#endif #endif
@ -3077,7 +3092,10 @@ static void transaction_start(thread_db* tdbb, jrd_tra* trans)
} }
else else
{ {
const header_page* header = bump_transaction_id(tdbb, &window); const bool dontWrite = (dbb->dbb_flags & DBB_shared) &&
(trans->tra_flags & TRA_readonly);
const header_page* header = bump_transaction_id(tdbb, &window, dontWrite);
number = Ods::getNT(header); number = Ods::getNT(header);
oldest = Ods::getOIT(header); oldest = Ods::getOIT(header);
oldest_active = Ods::getOAT(header); oldest_active = Ods::getOAT(header);