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

Attempted to fix CORE-3490: Concurrency problem when using named cursors. The solution may look sub-optimal but it doesn't seem to affect the performance.

This commit is contained in:
dimitr 2011-12-01 09:24:59 +00:00
parent 3970019916
commit e3fb73cdca

View File

@ -119,6 +119,7 @@ enum UndoDataRet {
static UndoDataRet get_undo_data(thread_db* tdbb, jrd_tra* transaction, record_param* rpb);
static void invalidate_cursor_records(jrd_tra*, record_param*);
static void list_staying(thread_db*, record_param*, RecordStack&);
static void notify_garbage_collector(thread_db*, record_param*, SLONG = -1);
static Record* realloc_record(Record*& record, USHORT fmt_length);
@ -1608,6 +1609,11 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
}
}
// We're about to erase the record. Post a refetch request
// to all the active cursors positioned at this record.
invalidate_cursor_records(transaction, rpb);
// If the page can be updated simply, we can skip the remaining crud
record_param temp;
@ -2582,6 +2588,11 @@ void VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j
}
}
// We're about to modify the record. Post a refetch request
// to all the active cursors positioned at this record.
invalidate_cursor_records(transaction, org_rpb);
// hvlad: prepare_update() take EX lock on data page. Subsequent call of
// IDX_modify_flag_uk_modified() will read database - if relation's partners
// list has not been scanned yet. It could lead to single thread deadlock
@ -4563,6 +4574,43 @@ static UndoDataRet get_undo_data(thread_db* tdbb, jrd_tra* transaction, record_p
}
static void invalidate_cursor_records(jrd_tra* transaction, record_param* mod_rpb)
{
/**************************************
*
* i n v a l i d a t e _ c u r s o r _ r e c o r d s
*
**************************************
*
* Functional description
* Post a refetch request to the records currently fetched
* by active cursors of our transaction, because those records
* have just been updated or deleted.
*
**************************************/
fb_assert(mod_rpb && mod_rpb->rpb_relation);
for (jrd_req* request = transaction->tra_requests; request; request = request->req_tra_next)
{
if (request->req_flags & req_active)
{
for (size_t i = 0; i < request->req_count; i++)
{
record_param* const org_rpb = &request->req_rpb[i];
if (org_rpb != mod_rpb &&
org_rpb->rpb_relation && org_rpb->rpb_number.isValid() &&
org_rpb->rpb_relation->rel_id == mod_rpb->rpb_relation->rel_id &&
org_rpb->rpb_number == mod_rpb->rpb_number)
{
org_rpb->rpb_stream_flags |= RPB_s_refetch;
}
}
}
}
}
static void list_staying(thread_db* tdbb, record_param* rpb, RecordStack& staying)
{
/**************************************