Bug #101465 mysql doesn't release index sx latch properly in page split operation
Submitted: 5 Nov 2020 1:03 Modified: 6 Nov 2020 13:10
Reporter: wei wang (OCA) Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S5 (Performance)
Version:8.0 OS:Any
Assigned to: CPU Architecture:Any

[5 Nov 2020 1:03] wei wang
Description:
Sometimes, it's safe to release index sx latch before mtr commit. mysql calls below statement to release sx latch:

    mtr->memo_release(dict_index_get_lock(cursor->index),
                      MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK);
but in mtr->memo_release, the type is MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK = 128 + 256 = 384. Function mtr::memo_release uses Find::operator() to find the sx latch, and in Find::operator() it uses below condition:

struct Find {
  /** Constructor */
  Find(const void *object, ulint type)
      : m_slot(), m_type(type), m_object(object) {
    ut_a(object != nullptr);
  }

  /** @return false if the object was found. */
  bool operator()(mtr_memo_slot_t *slot) {
    if (m_object == slot->object && m_type == slot->type) {
      m_slot = slot;
      return (false);
    }

    return (true);
  }

It uses m_type == slot->type to find the index lock object, that is slot->type == MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK = 128 + 256 = 384, which doesn't exist. It should use conditon m_type & slot->type.

So, all the places with calls
mtr->memo_release(dict_index_get_lock(cursor->index), MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK);
to release index sx latch doesn't succeed.

How to repeat:
You can add a breakpoint to that function and do a lot of insert to a table.

Suggested fix:
diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc
index 41334ba0ce6..b348e38fe8a 100644
--- a/storage/innobase/mtr/mtr0mtr.cc
+++ b/storage/innobase/mtr/mtr0mtr.cc
@@ -99,7 +99,7 @@ struct Find {

   /** @return false if the object was found. */
   bool operator()(mtr_memo_slot_t *slot) {
-    if (m_object == slot->object && m_type == slot->type) {
+    if (m_object == slot->object && (m_type & slot->type)) {
       m_slot = slot;
       return (false);
     }
[5 Nov 2020 13:22] MySQL Verification Team
Hi Mr. wang,

Thank you for your performance regression report.

However, in the latest 8.0.22 micro transactions source there is no source code that is OR-ing those two types of locks .......

Grateful in advance for your feedback.
[6 Nov 2020 3:43] wei wang
from the latest 8.0.22 source code on github: https://github.com/mysql/mysql-server/blob/8.0/storage/innobase/btr/btr0btr.cc, there still are some places which early release sx latch, like below:

  if (!srv_read_only_mode && !cursor->index->table->is_intrinsic() &&
      insert_will_fit && page_is_leaf(page) &&
      !dict_index_is_online_ddl(cursor->index)) {
    mtr->memo_release(dict_index_get_lock(cursor->index),
                      MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK);

    /* NOTE: We cannot release root block latch here, because it
    has segment header and already modified in most of cases.*/
  }
[6 Nov 2020 3:49] wei wang
below are 3 places:
1. function btr_page_split_and_insert in https://github.com/mysql/mysql-server/blob/8.0/storage/innobase/btr/btr0btr.cc
  if (!srv_read_only_mode && !cursor->index->table->is_intrinsic() &&
      insert_will_fit && page_is_leaf(page) &&
      !dict_index_is_online_ddl(cursor->index)) {
    mtr->memo_release(dict_index_get_lock(cursor->index),
                      MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK);

2. function btr_cur_pessimistic_update, btr_cur_pessimistic_delete in https://github.com/mysql/mysql-server/blob/8.0/storage/innobase/btr/btr0cur.cc
    if (!srv_read_only_mode && !big_rec_vec && page_is_leaf(page) &&
        !dict_index_is_online_ddl(index)) {
      mtr_memo_release(mtr, dict_index_get_lock(index),
                       MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK);

      /* NOTE: We cannot release root block latch here, because it
      has segment header and already modified in most of cases.*/
    }
[6 Nov 2020 13:10] MySQL Verification Team
Hi Mr. wang,

Thank you for your feedback.

You are correct.

Verified as reported.