8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 18:43:02 +01:00

Fix #7700 - SKIP LOCKED returns conflict error or wait when config ReadConsistency = 0 (#7701)

* Fix #7700 - SKIP LOCKED returns conflict error or wait when config ReadConsistency = 0.

* Rename RecordLock::DONT to NONE.
This commit is contained in:
Adriano dos Santos Fernandes 2023-09-12 21:50:06 -03:00 committed by GitHub
parent de99d190f2
commit 5b14baa37b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 28 additions and 20 deletions

View File

@ -2658,7 +2658,7 @@ const StmtNode* EraseNode::erase(thread_db* tdbb, Request* request, WhichTrigger
if (rpb->rpb_runtime_flags & RPB_refetch)
{
VIO_refetch_record(tdbb, rpb, transaction, false, false);
VIO_refetch_record(tdbb, rpb, transaction, RecordLock::NONE, false);
rpb->rpb_runtime_flags &= ~RPB_refetch;
}
@ -7112,7 +7112,7 @@ const StmtNode* ModifyNode::modify(thread_db* tdbb, Request* request, WhichTrigg
if (orgRpb->rpb_runtime_flags & RPB_refetch)
{
VIO_refetch_record(tdbb, orgRpb, transaction, false, false);
VIO_refetch_record(tdbb, orgRpb, transaction, RecordLock::NONE, false);
orgRpb->rpb_runtime_flags &= ~RPB_refetch;
}
@ -10547,9 +10547,9 @@ static void cleanupRpb(thread_db* tdbb, record_param* rpb)
}
// Try to set write lock on record until success or record exists
static void forceWriteLock(thread_db * tdbb, record_param * rpb, jrd_tra * transaction)
static void forceWriteLock(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
{
while (VIO_refetch_record(tdbb, rpb, transaction, true, true))
while (VIO_refetch_record(tdbb, rpb, transaction, RecordLock::LOCK, true))
{
rpb->rpb_runtime_flags &= ~RPB_refetch;

View File

@ -240,7 +240,7 @@ bool RecordStream::refetchRecord(thread_db* tdbb) const
if (rpb->rpb_runtime_flags & RPB_refetch)
{
if (VIO_refetch_record(tdbb, rpb, transaction, true, false))
if (VIO_refetch_record(tdbb, rpb, transaction, RecordLock::LOCK, false))
{
rpb->rpb_runtime_flags &= ~RPB_refetch;
return true;

View File

@ -478,7 +478,7 @@ void SortedStream::mapData(thread_db* tdbb, Request* request, UCHAR* data) const
tdbb->bumpRelStats(RuntimeStatistics::RECORD_RPT_READS, relation->rel_id);
if (VIO_chase_record_version(tdbb, &temp, transaction, tdbb->getDefaultPool(), false, false))
if (VIO_chase_record_version(tdbb, &temp, transaction, tdbb->getDefaultPool(), RecordLock::NONE, false))
{
if (!(temp.rpb_runtime_flags & RPB_undo_data))
VIO_data(tdbb, &temp, tdbb->getDefaultPool());

View File

@ -1109,7 +1109,7 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction)
bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
jrd_tra* transaction, MemoryPool* pool,
bool writelock, bool noundo)
RecordLock recordLock, bool noundo)
{
/**************************************
*
@ -1258,9 +1258,10 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
// If the transaction is a read committed and chooses the no version
// option, wait for reads also!
if ((transaction->tra_flags & TRA_read_committed) &&
if (recordLock != RecordLock::SKIP &&
(transaction->tra_flags & TRA_read_committed) &&
!(transaction->tra_flags & TRA_read_consistency) &&
(!(transaction->tra_flags & TRA_rec_version) || writelock))
(!(transaction->tra_flags & TRA_rec_version) || recordLock == RecordLock::LOCK))
{
if (state == tra_limbo)
{
@ -1975,7 +1976,7 @@ bool VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
if (rpb->rpb_runtime_flags & (RPB_refetch | RPB_undo_read))
{
VIO_refetch_record(tdbb, rpb, transaction, false, true);
VIO_refetch_record(tdbb, rpb, transaction, RecordLock::NONE, true);
rpb->rpb_runtime_flags &= ~RPB_refetch;
fb_assert(!(rpb->rpb_runtime_flags & RPB_undo_read));
}
@ -2905,7 +2906,7 @@ bool VIO_get(thread_db* tdbb, record_param* rpb, jrd_tra* transaction, MemoryPoo
const USHORT lock_type = (rpb->rpb_stream_flags & RPB_s_update) ? LCK_write : LCK_read;
if (!DPM_get(tdbb, rpb, lock_type) ||
!VIO_chase_record_version(tdbb, rpb, transaction, pool, false, false))
!VIO_chase_record_version(tdbb, rpb, transaction, pool, RecordLock::NONE, false))
{
return false;
}
@ -3280,7 +3281,7 @@ bool VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j
old_record->copyFrom(org_rpb->rpb_record);
}
VIO_refetch_record(tdbb, org_rpb, transaction, false, true);
VIO_refetch_record(tdbb, org_rpb, transaction, RecordLock::NONE, true);
org_rpb->rpb_runtime_flags &= ~RPB_refetch;
fb_assert(!(org_rpb->rpb_runtime_flags & RPB_undo_read));
@ -3763,7 +3764,7 @@ bool VIO_next_record(thread_db* tdbb,
{
return false;
}
} while (!VIO_chase_record_version(tdbb, rpb, transaction, pool, false, false));
} while (!VIO_chase_record_version(tdbb, rpb, transaction, pool, RecordLock::NONE, false));
if (rpb->rpb_runtime_flags & RPB_undo_data)
fb_assert(rpb->getWindow(tdbb).win_bdb == NULL);
@ -3841,7 +3842,7 @@ Record* VIO_record(thread_db* tdbb, record_param* rpb, const Format* format, Mem
bool VIO_refetch_record(thread_db* tdbb, record_param* rpb, jrd_tra* transaction,
bool writelock, bool noundo)
RecordLock recordLock, bool noundo)
{
/**************************************
*
@ -3864,9 +3865,9 @@ bool VIO_refetch_record(thread_db* tdbb, record_param* rpb, jrd_tra* transaction
const TraNumber tid_fetch = rpb->rpb_transaction_nr;
if (!DPM_get(tdbb, rpb, LCK_read) ||
!VIO_chase_record_version(tdbb, rpb, transaction, tdbb->getDefaultPool(), writelock, noundo))
!VIO_chase_record_version(tdbb, rpb, transaction, tdbb->getDefaultPool(), recordLock, noundo))
{
if (writelock)
if (recordLock == RecordLock::LOCK)
return false;
ERR_post(Arg::Gds(isc_no_cur_rec));
@ -3890,7 +3891,7 @@ bool VIO_refetch_record(thread_db* tdbb, record_param* rpb, jrd_tra* transaction
// make sure the record has not been updated. Also, punt after
// VIO_data() call which will release the page.
if (!writelock &&
if (recordLock != RecordLock::LOCK &&
(transaction->tra_flags & TRA_read_committed) &&
(tid_fetch != rpb->rpb_transaction_nr) &&
// added to check that it was not current transaction,
@ -4486,7 +4487,7 @@ WriteLockResult VIO_writelock(thread_db* tdbb, record_param* org_rpb, jrd_tra* t
if (org_rpb->rpb_runtime_flags & (RPB_refetch | RPB_undo_read))
{
if (!VIO_refetch_record(tdbb, org_rpb, transaction, true, true))
if (!VIO_refetch_record(tdbb, org_rpb, transaction, (skipLocked ? RecordLock::SKIP : RecordLock::LOCK), true))
return WriteLockResult::CONFLICTED;
org_rpb->rpb_runtime_flags &= ~RPB_refetch;

View File

@ -44,6 +44,13 @@ namespace Jrd
DPM_next_pointer_page // data pages from one pointer page
};
enum class RecordLock
{
NONE,
LOCK,
SKIP
};
enum class WriteLockResult
{
LOCKED,
@ -54,7 +61,7 @@ namespace Jrd
void VIO_backout(Jrd::thread_db*, Jrd::record_param*, const Jrd::jrd_tra*);
bool VIO_chase_record_version(Jrd::thread_db*, Jrd::record_param*,
Jrd::jrd_tra*, MemoryPool*, bool, bool);
Jrd::jrd_tra*, MemoryPool*, Jrd::RecordLock, bool);
void VIO_copy_record(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::Record*, Jrd::Record*);
void VIO_data(Jrd::thread_db*, Jrd::record_param*, MemoryPool*);
bool VIO_erase(Jrd::thread_db*, Jrd::record_param*, Jrd::jrd_tra*);
@ -69,7 +76,7 @@ Jrd::WriteLockResult VIO_writelock(Jrd::thread_db*, Jrd::record_param*, Jrd::jrd
bool VIO_modify(Jrd::thread_db*, Jrd::record_param*, Jrd::record_param*, Jrd::jrd_tra*);
bool VIO_next_record(Jrd::thread_db*, Jrd::record_param*, Jrd::jrd_tra*, MemoryPool*, Jrd::FindNextRecordScope);
Jrd::Record* VIO_record(Jrd::thread_db*, Jrd::record_param*, const Jrd::Format*, MemoryPool*);
bool VIO_refetch_record(Jrd::thread_db*, Jrd::record_param*, Jrd::jrd_tra*, bool, bool);
bool VIO_refetch_record(Jrd::thread_db*, Jrd::record_param*, Jrd::jrd_tra*, Jrd::RecordLock, bool);
void VIO_store(Jrd::thread_db*, Jrd::record_param*, Jrd::jrd_tra*);
bool VIO_sweep(Jrd::thread_db*, Jrd::jrd_tra*, Jrd::TraceSweepEvent*);
void VIO_intermediate_gc(Jrd::thread_db* tdbb, Jrd::record_param* rpb, Jrd::jrd_tra* transaction);