Skip to content
  • Olav Sandstaa's avatar
    2a521e97
    Fix for Bug#41029 MRR: SELECT FOR UPDATE fails to lock gaps (InnoDB table) · 2a521e97
    Olav Sandstaa authored
          
    This problem occurs due to MRR is creating a second handler
    object. This handler object is a "clone" of the first/initial handler
    object and the MRR code use this second handler object for executing
    some of the operations.
          
    The second handler object is created in DsMRR_impl::dsmrr_init() (in
    handler.cc) by "cloning" the initial handler object:
          
         if (!(new_h2= h->clone(thd->mem_root)) || 
             new_h2->ha_external_lock(thd, F_RDLCK))
          
    The important thing about the above code is that on this cloned
    handler object a call to ha_external_lock() is done with a request to
    use a read lock (F_RDLCK). When this handler object (h2) is used in
    DsMrr_impl::dsmrr_fill_buffer() for doing the initial search for the
    first record in the range interval, the index search done by InnoDB
    will be done without setting any exclusive lock on the search
    interval. This allows a second transaction to succeed to insert data
    within the "read interval" of the first transaction.
          
    The fix for this problem is to use the same lock type when calling
    new_h2->ha_external_lock() as was done on the original handler
    object. To do this we store (in handler::ha_external_lock()) the
    original lock type in a new member variable in the handler object
    (m_lock_type) and use this lock type when "cloning" the handler object
    in DsMRR_impl::dsmrr_init().
    2a521e97
    Fix for Bug#41029 MRR: SELECT FOR UPDATE fails to lock gaps (InnoDB table)
    Olav Sandstaa authored
          
    This problem occurs due to MRR is creating a second handler
    object. This handler object is a "clone" of the first/initial handler
    object and the MRR code use this second handler object for executing
    some of the operations.
          
    The second handler object is created in DsMRR_impl::dsmrr_init() (in
    handler.cc) by "cloning" the initial handler object:
          
         if (!(new_h2= h->clone(thd->mem_root)) || 
             new_h2->ha_external_lock(thd, F_RDLCK))
          
    The important thing about the above code is that on this cloned
    handler object a call to ha_external_lock() is done with a request to
    use a read lock (F_RDLCK). When this handler object (h2) is used in
    DsMrr_impl::dsmrr_fill_buffer() for doing the initial search for the
    first record in the range interval, the index search done by InnoDB
    will be done without setting any exclusive lock on the search
    interval. This allows a second transaction to succeed to insert data
    within the "read interval" of the first transaction.
          
    The fix for this problem is to use the same lock type when calling
    new_h2->ha_external_lock() as was done on the original handler
    object. To do this we store (in handler::ha_external_lock()) the
    original lock type in a new member variable in the handler object
    (m_lock_type) and use this lock type when "cloning" the handler object
    in DsMRR_impl::dsmrr_init().
Loading