Bug #113760 Insufficient memory barriers in rw-lock implementation caused crash on ARM arch

Submitted: 25 Jan 2024 13:00 Modified: 25 Jan 2024 14:00
Reporter: Brian Yue (OCA) Email Updates:
Status: Unsupported Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S3 (Non-critical)
Version:5.7.44 OS:Linux
Assigned to: CPU Architecture:ARM
Tags: arm, crash, memory barrier

[25 Jan 2024 13:00] Brian Yue
Description:
Hello,
  We recently found several crashes of MySQL 5.7 on ARM architecture, and finally fix it.
  The reason is similar with the previously fixed bug  "Bug #29508001 MYSQL DEADLOCK AND BUGCHECK ON AARCH64 UNDER STRESS TEST" but not the same function. There are three rw-lock functions which have similar implementation that suffer with weakly ordered model of memory on ARM:
  1. rw_lock_x_lock_low in storage/innobase/sync/sync0rw.cc
  2. rw_lock_sx_lock_low in storage/innobase/sync/sync0rw.cc
  3. rw_lock_x_lock_func_nowait in storage/innobase/include/sync0rw.ic

  In MySQL 5.7, only rw_lock_x_lock_low and rw_lock_sx_lock_low is fixed in "Bug #29508001 MYSQL DEADLOCK AND BUGCHECK ON AARCH64 UNDER STRESS TEST", missing rw_lock_x_lock_func_nowait.

  However, in MySQL 8.0.20 rw_lock_x_lock_func_nowait is fixed by "Bug #30401416 RWLOCK:REFINE LOCK->RECURSIVE WITH C11 ATOMICS" using std::atomic in a modern c++ way:
```
    if (!pass && lock->recursive.load(std::memory_order_acquire) &&
        os_thread_eq(lock->writer_thread, os_thread_get_curr_id())) {
```
  But this modification is not backported to MySQL 5.7, so crash or deadlock happens because of cocurrent rwlock request through rw_lock_x_lock_func_nowait. I guess it could be a mistake. On my mysql server, if app keeps deleting many records, maybe the DML thread and bg purge thread or ibuf merge operation are modifying the buffer page concurretly and causing a damaged page due to useless rwlock mechanism.

How to repeat:
It's a issue that is not easy to reproduce, but I believe the previous code analysis is enough. However, the method to produce the issue is followed:

(1) make a table with 10,000,000 records using sysbench
(2) keep deleting batch records, each time we delete 1000 records in a transaction:
delete from sbtest1 limit 1000;
(3) keep trying ...

Suggested fix:
diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic
index c48df97..5a62593 100644
--- a/storage/innobase/include/sync0rw.ic
+++ b/storage/innobase/include/sync0rw.ic
@@ -462,12 +462,27 @@ rw_lock_x_lock_func_nowait(
        mutex_exit(&(lock->mutex));

 #endif
-       if (success) {
-               rw_lock_set_writer_id_and_recursion_flag(lock, true);

-       } else if (lock->recursive
-                  && os_thread_eq(lock->writer_thread,
-                                  os_thread_get_curr_id())) {
+       /*
+               Same question as GDB-325546, use os_rmb to fit in 5.7* VERSION.
+               Fix in 8.0 VERSION see <Bug #30401416>.
+       */
+       bool recursive;
+       os_thread_id_t writer_thread;
+       if (!success)
+       {
+               recursive = lock->recursive;
+               os_rmb;
+               writer_thread = lock->writer_thread;
+       }
+
+       if (success)
+       {
+               rw_lock_set_writer_id_and_recursion_flag(lock, true);
+       }
+       else if (recursive && os_thread_eq(writer_thread,
+                                     os_thread_get_curr_id()))
+       {
                /* Relock: this lock_word modification is safe since no other
                threads can modify (lock, unlock, or reserve) lock_word while
                there is an exclusive writer and this is the writer thread. */
[25 Jan 2024 14:00] MySQL Verification Team
Hi Mr. Yue,

Thank you very much for your bug report.

However, we have to inform you that it has been a while since we stopped any maintenance of the version 5.7.

If you can provide a test case that crashes our 8.0.36 or 8.3.0 server, then please, do provide a test case in pure SQL !!!!!

Thanks in advance.

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.053 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.