mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 22:03:03 +01:00
Implemented CORE-3994: Improve the limbo transactions scan at the end of the sweep.
This commit is contained in:
parent
5eaecbbfc0
commit
87c65731bc
@ -100,6 +100,63 @@ int TPC_cache_state(thread_db* tdbb, SLONG number)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SLONG TPC_find_limbo(Jrd::thread_db* tdbb, SLONG min_number, SLONG max_number)
|
||||||
|
{
|
||||||
|
/**************************************
|
||||||
|
*
|
||||||
|
* T P C _ f i n d _ l i m b o
|
||||||
|
*
|
||||||
|
**************************************
|
||||||
|
*
|
||||||
|
* Functional description
|
||||||
|
* Return the oldest limbo transaction in the given boundaries.
|
||||||
|
* If not found, return zero.
|
||||||
|
*
|
||||||
|
**************************************/
|
||||||
|
SET_TDBB(tdbb);
|
||||||
|
Database* const dbb = tdbb->getDatabase();
|
||||||
|
CHECK_DBB(dbb);
|
||||||
|
|
||||||
|
fb_assert((ULONG) min_number <= (ULONG) max_number);
|
||||||
|
|
||||||
|
const SLONG trans_per_tip = dbb->dbb_page_manager.transPerTIP;
|
||||||
|
|
||||||
|
// Ensure that the TIP cache is extended to fit the requested transactions
|
||||||
|
|
||||||
|
TPC_initialize_tpc(tdbb, max_number);
|
||||||
|
const TxPageCache* tip_cache = dbb->dbb_tip_cache;
|
||||||
|
|
||||||
|
// All transactions older than the oldest in our TIP cache
|
||||||
|
// are known to be committed, so there's no point looking at them
|
||||||
|
|
||||||
|
if ((ULONG) max_number < (ULONG) tip_cache->tpc_base)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ((ULONG) min_number < (ULONG) tip_cache->tpc_base)
|
||||||
|
min_number = tip_cache->tpc_base;
|
||||||
|
|
||||||
|
// Scan the TIP cache and return the first (i.e. oldest) limbo transaction
|
||||||
|
|
||||||
|
for (ULONG number = min_number;
|
||||||
|
tip_cache && number <= (ULONG) max_number;
|
||||||
|
tip_cache = tip_cache->tpc_next)
|
||||||
|
{
|
||||||
|
if (number >= (ULONG) tip_cache->tpc_base)
|
||||||
|
{
|
||||||
|
for (; number < (ULONG) (tip_cache->tpc_base + trans_per_tip) &&
|
||||||
|
number <= (ULONG) max_number;
|
||||||
|
number++)
|
||||||
|
{
|
||||||
|
if (TRA_state(tip_cache->tpc_transactions, tip_cache->tpc_base, number) == tra_limbo)
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void TPC_initialize_tpc(thread_db* tdbb, SLONG number)
|
void TPC_initialize_tpc(thread_db* tdbb, SLONG number)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#define JRD_TPC_PROTO_H
|
#define JRD_TPC_PROTO_H
|
||||||
|
|
||||||
int TPC_cache_state(Jrd::thread_db*, SLONG);
|
int TPC_cache_state(Jrd::thread_db*, SLONG);
|
||||||
|
SLONG TPC_find_limbo(Jrd::thread_db*, SLONG, SLONG);
|
||||||
void TPC_initialize_tpc(Jrd::thread_db*, SLONG);
|
void TPC_initialize_tpc(Jrd::thread_db*, SLONG);
|
||||||
void TPC_set_state(Jrd::thread_db*, SLONG, SSHORT);
|
void TPC_set_state(Jrd::thread_db*, SLONG, SSHORT);
|
||||||
int TPC_snapshot_state(Jrd::thread_db*, SLONG);
|
int TPC_snapshot_state(Jrd::thread_db*, SLONG);
|
||||||
|
@ -1802,25 +1802,16 @@ void TRA_sweep(thread_db* tdbb)
|
|||||||
|
|
||||||
if (VIO_sweep(tdbb, transaction, &traceSweep))
|
if (VIO_sweep(tdbb, transaction, &traceSweep))
|
||||||
{
|
{
|
||||||
const ULONG base = transaction->tra_oldest & ~TRA_MASK;
|
// At this point, we know that no record versions belonging to dead
|
||||||
ULONG active = transaction->tra_oldest;
|
// transactions remain anymore. However, there may still be limbo
|
||||||
for (; active < (ULONG) transaction->tra_top; active++)
|
// transactions, so we need to find the oldest one between tra_oldest and tra_top.
|
||||||
{
|
// As our transaction is read-committed (see sweep_tpb), we have to scan
|
||||||
if (transaction->tra_flags & TRA_read_committed)
|
// the global TIP cache.
|
||||||
{
|
|
||||||
if (TPC_cache_state(tdbb, active) == tra_limbo)
|
const SLONG oldest_limbo =
|
||||||
break;
|
TPC_find_limbo(tdbb, transaction->tra_oldest, transaction->tra_top - 1);
|
||||||
}
|
|
||||||
else
|
const SLONG active = oldest_limbo ? oldest_limbo : transaction->tra_top;
|
||||||
{
|
|
||||||
const ULONG byte = TRANS_OFFSET(active - base);
|
|
||||||
const USHORT shift = TRANS_SHIFT(active);
|
|
||||||
if (((transaction->tra_transactions[byte] >> shift) & TRA_MASK) == tra_limbo)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flush page buffers to insure that no dangling records from
|
// Flush page buffers to insure that no dangling records from
|
||||||
// dead transactions are left on-disk. This must be done before
|
// dead transactions are left on-disk. This must be done before
|
||||||
@ -1838,7 +1829,7 @@ void TRA_sweep(thread_db* tdbb)
|
|||||||
if (header->hdr_oldest_transaction < --transaction_oldest_active)
|
if (header->hdr_oldest_transaction < --transaction_oldest_active)
|
||||||
{
|
{
|
||||||
CCH_MARK_MUST_WRITE(tdbb, &window);
|
CCH_MARK_MUST_WRITE(tdbb, &window);
|
||||||
header->hdr_oldest_transaction = MIN(active, (ULONG) transaction_oldest_active);
|
header->hdr_oldest_transaction = MIN((ULONG) active, (ULONG) transaction_oldest_active);
|
||||||
}
|
}
|
||||||
|
|
||||||
traceSweep.update(header);
|
traceSweep.update(header);
|
||||||
|
Loading…
Reference in New Issue
Block a user