Commit 6ff71d0d authored by Annamalai Gurusami's avatar Annamalai Gurusami

Bug #14226171 EXCESSIVE ROW LOCKING WITH UPDATE IN 5.5.25

When a DML statement is issued, and if the index merge 
access method is chosen, then many rows from the
storage engine will be locked because of the way the
algorithm works.  Many rows will be locked, but they
will not be part of the final result set.

To reduce the excessive locking, the locks of unmatched
rows are released by this patch.  This patch will 
affect only transactions with isolation level
equal to or less stricter than READ COMMITTED. This is
because of the behaviour of ha_innobase::unlock_row().

rb://1296 approved by jorgen and olav.
parent 44beb951
......@@ -8412,6 +8412,13 @@ int QUICK_INDEX_MERGE_SELECT::get_next()
If a Clustered PK scan is present, it is used only to check if row
satisfies its condition (and never used for row retrieval).
Locking: to ensure that exclusive locks are only set on records that
are included in the final result we must release the lock
on all rows we read but do not include in the final result. This
must be done on each index that reads the record and the lock
must be released using the same handler (the same quick object) as
used when reading the record.
RETURN
0 - Ok
other - Error code if any error occurred.
......@@ -8421,6 +8428,12 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
{
List_iterator_fast<QUICK_RANGE_SELECT> quick_it(quick_selects);
QUICK_RANGE_SELECT* quick;
/* quick that reads the given rowid first. This is needed in order
to be able to unlock the row using the same handler object that locked
it */
QUICK_RANGE_SELECT* quick_with_last_rowid;
int error, cmp;
uint last_rowid_count=0;
DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::get_next");
......@@ -8433,7 +8446,10 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
if (cpk_quick)
{
while (!error && !cpk_quick->row_in_ranges())
{
quick->file->unlock_row(); /* row not in range; unlock */
error= quick->get_next();
}
}
if (error)
DBUG_RETURN(error);
......@@ -8441,6 +8457,7 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
quick->file->position(quick->record);
memcpy(last_rowid, quick->file->ref, head->file->ref_length);
last_rowid_count= 1;
quick_with_last_rowid= quick;
while (last_rowid_count < quick_selects.elements)
{
......@@ -8453,9 +8470,17 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
do
{
if ((error= quick->get_next()))
{
quick_with_last_rowid->file->unlock_row();
DBUG_RETURN(error);
}
quick->file->position(quick->record);
cmp= head->file->cmp_ref(quick->file->ref, last_rowid);
if (cmp < 0)
{
/* This row is being skipped. Release lock on it. */
quick->file->unlock_row();
}
} while (cmp < 0);
/* Ok, current select 'caught up' and returned ref >= cur_ref */
......@@ -8466,13 +8491,19 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
{
while (!cpk_quick->row_in_ranges())
{
quick->file->unlock_row(); /* row not in range; unlock */
if ((error= quick->get_next()))
{
quick_with_last_rowid->file->unlock_row();
DBUG_RETURN(error);
}
}
quick->file->position(quick->record);
}
memcpy(last_rowid, quick->file->ref, head->file->ref_length);
quick_with_last_rowid->file->unlock_row();
last_rowid_count= 1;
quick_with_last_rowid= quick;
}
else
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment