mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 18:03:04 +01:00
Improvement CORE-3536 : Garbage collection in GTT is unnecessary delayed by active transactions in another attachments
This commit is contained in:
parent
7c68e15a0f
commit
f2aaa12ce5
@ -229,6 +229,7 @@ public:
|
||||
UserId* att_user; // User identification
|
||||
jrd_tra* att_transactions; // Transactions belonging to attachment
|
||||
jrd_tra* att_dbkey_trans; // transaction to control db-key scope
|
||||
SLONG att_oldest_snapshot; // GTT's record versions older than this can be gargage-collected
|
||||
|
||||
private:
|
||||
jrd_tra* att_sys_transaction; // system transaction
|
||||
|
@ -3432,6 +3432,23 @@ static jrd_tra* transaction_start(thread_db* tdbb, jrd_tra* temp)
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate attachment-local oldest active and oldest snapshot numbers
|
||||
// looking at current attachment's transactions only. Calculated values
|
||||
// are used to determine garbage collection treshold for attachment-local
|
||||
// data such as temporary tables (GTT's).
|
||||
|
||||
trans->tra_att_oldest_active = number;
|
||||
SLONG att_oldest_active = number;
|
||||
SLONG att_oldest_snapshot = number;
|
||||
for (jrd_tra* tx_att = attachment->att_transactions; tx_att; tx_att = tx_att->tra_next)
|
||||
{
|
||||
att_oldest_active = MIN(att_oldest_active, tx_att->tra_number);
|
||||
att_oldest_snapshot = MIN(att_oldest_snapshot, tx_att->tra_att_oldest_active);
|
||||
}
|
||||
trans->tra_att_oldest_active = (trans->tra_flags & TRA_read_committed) ? number : att_oldest_active;
|
||||
if (attachment->att_oldest_snapshot < att_oldest_snapshot)
|
||||
attachment->att_oldest_snapshot = att_oldest_snapshot;
|
||||
|
||||
// Put the TID of the oldest active transaction (just calculated)
|
||||
// in the new transaction's lock.
|
||||
// hvlad: for read-committed transaction put tra_number to prevent
|
||||
|
@ -232,6 +232,7 @@ public:
|
||||
SLONG tra_oldest; // oldest interesting transaction
|
||||
SLONG tra_oldest_active; // record versions older than this can be
|
||||
// gargage-collected by this tx
|
||||
SLONG tra_att_oldest_active; // oldest active transaction in the same attachment
|
||||
jrd_tra* tra_next; // next transaction in database
|
||||
jrd_tra* tra_sibling; // next transaction in group
|
||||
MemoryPool* const tra_pool; // pool for transaction
|
||||
|
@ -546,9 +546,12 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
|
||||
*
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
Jrd::Attachment* attachment = transaction->tra_attachment;
|
||||
|
||||
const bool gcPolicyCooperative = tdbb->getDatabase()->dbb_flags & DBB_gc_cooperative;
|
||||
const bool gcPolicyBackground = tdbb->getDatabase()->dbb_flags & DBB_gc_background;
|
||||
const SLONG oldest_snapshot =
|
||||
rpb->rpb_relation->isTemporary() ? attachment->att_oldest_snapshot : transaction->tra_oldest_active;
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
if (debug_flag > DEBUG_TRACE_ALL)
|
||||
@ -617,7 +620,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
|
||||
|
||||
if ((state == tra_committed || state == tra_us) && !forceBack &&
|
||||
!(rpb->rpb_flags & (rpb_deleted | rpb_damaged)) &&
|
||||
(rpb->rpb_b_page == 0 || rpb->rpb_transaction_nr >= transaction->tra_oldest_active))
|
||||
(rpb->rpb_b_page == 0 || rpb->rpb_transaction_nr >= oldest_snapshot))
|
||||
{
|
||||
if (gcPolicyBackground && rpb->rpb_b_page)
|
||||
notify_garbage_collector(tdbb, rpb);
|
||||
@ -625,8 +628,6 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
|
||||
return true;
|
||||
}
|
||||
|
||||
Jrd::Attachment* attachment = transaction->tra_attachment;
|
||||
|
||||
// OK, something about the record is fishy. Loop thru versions until a
|
||||
// satisfactory version is found or we run into a brick wall. Do any
|
||||
// garbage collection that seems appropriate.
|
||||
@ -976,7 +977,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
|
||||
#endif
|
||||
if (rpb->rpb_flags & rpb_deleted)
|
||||
{
|
||||
if (rpb->rpb_transaction_nr < transaction->tra_oldest_active &&
|
||||
if (rpb->rpb_transaction_nr < oldest_snapshot &&
|
||||
!(attachment->att_flags & ATT_no_cleanup))
|
||||
{
|
||||
if (!gcPolicyCooperative && (attachment->att_flags & ATT_notify_gc) &&
|
||||
@ -1003,7 +1004,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
|
||||
// That might be the reason for the rpb_chained check.
|
||||
|
||||
const bool cannotGC =
|
||||
rpb->rpb_transaction_nr >= transaction->tra_oldest_active || rpb->rpb_b_page == 0 ||
|
||||
rpb->rpb_transaction_nr >= oldest_snapshot || rpb->rpb_b_page == 0 ||
|
||||
rpb->rpb_flags & rpb_chained || attachment->att_flags & ATT_no_cleanup;
|
||||
|
||||
if (cannotGC)
|
||||
@ -1732,6 +1733,7 @@ bool VIO_garbage_collect(thread_db* tdbb, record_param* rpb, const jrd_tra* tran
|
||||
*
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
Jrd::Attachment* attachment = transaction->tra_attachment;
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
if (debug_flag > DEBUG_TRACE)
|
||||
@ -1750,10 +1752,13 @@ bool VIO_garbage_collect(thread_db* tdbb, record_param* rpb, const jrd_tra* tran
|
||||
}
|
||||
#endif
|
||||
|
||||
if (transaction->tra_attachment->att_flags & ATT_no_cleanup) {
|
||||
if (attachment->att_flags & ATT_no_cleanup) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const SLONG oldest_snapshot =
|
||||
rpb->rpb_relation->isTemporary() ? attachment->att_oldest_snapshot : transaction->tra_oldest_active;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (rpb->rpb_flags & rpb_damaged)
|
||||
@ -1800,7 +1805,7 @@ bool VIO_garbage_collect(thread_db* tdbb, record_param* rpb, const jrd_tra* tran
|
||||
{
|
||||
if (rpb->rpb_flags & rpb_deleted)
|
||||
{
|
||||
if (rpb->rpb_transaction_nr >= transaction->tra_oldest_active)
|
||||
if (rpb->rpb_transaction_nr >= oldest_snapshot)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -1810,7 +1815,7 @@ bool VIO_garbage_collect(thread_db* tdbb, record_param* rpb, const jrd_tra* tran
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rpb->rpb_transaction_nr >= transaction->tra_oldest_active || rpb->rpb_b_page == 0)
|
||||
if (rpb->rpb_transaction_nr >= oldest_snapshot || rpb->rpb_b_page == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -3633,7 +3638,7 @@ static int check_precommitted(const jrd_tra* transaction, const record_param* rp
|
||||
* Functional description
|
||||
* Check if precommitted transaction which created given record version is
|
||||
* current transaction or it is a still active and belongs to the current
|
||||
* attachment. This is needed to detect visibility of records modified by
|
||||
* attachment. This is needed to detect visibility of records modified in
|
||||
* temporary tables in read-only transactions.
|
||||
*
|
||||
**************************************/
|
||||
@ -3981,6 +3986,7 @@ static void expunge(thread_db* tdbb, record_param* rpb, const jrd_tra* transacti
|
||||
*
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
Jrd::Attachment* attachment = transaction->tra_attachment;
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
if (debug_flag > DEBUG_WRITES)
|
||||
@ -3992,7 +3998,7 @@ static void expunge(thread_db* tdbb, record_param* rpb, const jrd_tra* transacti
|
||||
}
|
||||
#endif
|
||||
|
||||
if (transaction->tra_attachment->att_flags & ATT_no_cleanup) {
|
||||
if (attachment->att_flags & ATT_no_cleanup) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4021,7 +4027,10 @@ static void expunge(thread_db* tdbb, record_param* rpb, const jrd_tra* transacti
|
||||
|
||||
// Make sure it looks kosher and delete the record.
|
||||
|
||||
if (!(rpb->rpb_flags & rpb_deleted) || rpb->rpb_transaction_nr >= transaction->tra_oldest_active)
|
||||
const SLONG oldest_snapshot =
|
||||
rpb->rpb_relation->isTemporary() ? attachment->att_oldest_snapshot : transaction->tra_oldest_active;
|
||||
|
||||
if (!(rpb->rpb_flags & rpb_deleted) || rpb->rpb_transaction_nr >= oldest_snapshot)
|
||||
{
|
||||
|
||||
// expunge
|
||||
|
Loading…
Reference in New Issue
Block a user