MySQL:RR分析死锁一列

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 水平有限 有误请指出版本:Percona MySQL 5.7.22对于锁的学习我做了一些输出详细参考如下:https://github.com/gaopengcarl/percona-server-locks-detail-5.7.22.git其中有readme 本文也是一个朋友问我死锁问题。

水平有限 有误请指出
版本:Percona MySQL 5.7.22
对于锁的学习我做了一些输出详细参考如下:
https://github.com/gaopengcarl/percona-server-locks-detail-5.7.22.git
其中有readme


本文也是一个朋友问我死锁问题。@越前

一、问题提出

如下构造方式,问为什么RC模式下不会死锁,RR模式下死锁。

drop table tt;

CREATE TABLE `tt` (
  `id` int(11) NOT NULL,
  `c1` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `c1` (`c1`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert into tt values(1,1);
session 1 session 2
begin;
select * from tt where c1=1 for update;
update tt set id=2 where c1=1;
begin;select * from tt where c1=1 for update;堵塞
select * from tt where c1=1 for update;
死锁回滚

二、分析方式

首先分析session 1 第一句:

select * from tt where c1=1 for update;
执行后的加锁行为

  • RR
---TRANSACTION 231106, ACTIVE 9 sec
3 lock struct(s), heap size 1160, 2 row lock(s)
MySQL thread id 11, OS thread handle 140737153623808, query id 303 localhost root
TABLE LOCK table `test`.`tt` trx id 231106 lock mode IX
RECORD LOCKS space id 127 page no 4 n bits 72 index c1 of table `test`.`tt` trx id 231106 lock_mode X(LOCK_X) locks rec but not gap(LOCK_REC_NOT_GAP)
Record lock, heap no 2 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 4; hex 80000001; asc     ;;

RECORD LOCKS space id 127 page no 3 n bits 72 index PRIMARY of table `test`.`tt` trx id 231106 lock_mode X(LOCK_X) locks rec but not gap(LOCK_REC_NOT_GAP)
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 0000000386c0; asc       ;;
 2: len 7; hex aa0000003f0110; asc     ?  ;;
 3: len 4; hex 80000001; asc     ;;
  • RC
---TRANSACTION 231105, ACTIVE 7 sec
3 lock struct(s), heap size 1160, 2 row lock(s)
MySQL thread id 11, OS thread handle 140737153623808, query id 295 localhost root
TABLE LOCK table `test`.`tt` trx id 231105 lock mode IX
RECORD LOCKS space id 127 page no 4 n bits 72 index c1 of table `test`.`tt` trx id 231105 lock_mode X(LOCK_X) locks rec but not gap(LOCK_REC_NOT_GAP)
Record lock, heap no 2 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 4; hex 80000001; asc     ;;

RECORD LOCKS space id 127 page no 3 n bits 72 index PRIMARY of table `test`.`tt` trx id 231105 lock_mode X(LOCK_X) locks rec but not gap(LOCK_REC_NOT_GAP)
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 0000000386c0; asc       ;;
 2: len 7; hex aa0000003f0110; asc     ?  ;;
 3: len 4; hex 80000001; asc     ;;

我们可以看到因为 c1是主键因此加锁方式不管怎么样都是LOCK_X|LOCK_REC_NOT_GAP,主键上也是同样的。就是锁住了二级唯一索引和主键的相关记录。

然后分析session 1 第二句:

update tt set id=2 where c1=1;
执行后的加锁行为

这一句比较重要,在二级唯一索引c1上会做一个删除和插入操作,也就是会将原来的1,1记录标记为del flag,同时插入2,1这条记录,这会引起一个锁的继承操作(lock_rec_inherit_to_gap_if_gap_lock调用会出现GAP LOCK),但是之前还会涉及到唯一性检查因此还涉及到LOCK_S锁和next key lock的存在(对于二级索引做唯一性检查始终是next key lock)。这里的del flag也是形成死锁的重要原因。(对于二级索引的update操作总是先删除然后插入记录,主键则会进行判断是否可以容下新的记录)

  • RR
---TRANSACTION 231106, ACTIVE 1626 sec
5 lock struct(s), heap size 1160, 5 row lock(s), undo log entries 2
MySQL thread id 11, OS thread handle 140737153623808, query id 305 localhost root
TABLE LOCK table `test`.`tt` trx id 231106 lock mode IX
RECORD LOCKS space id 127 page no 4 n bits 72 index c1 of table `test`.`tt` trx id 231106 lock_mode X(LOCK_X) locks rec but not gap(LOCK_REC_NOT_GAP)
Record lock, heap no 2 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
 0: len 4; hex 80000001; asc     ;;
 1: len 4; hex 80000001; asc     ;;

RECORD LOCKS space id 127 page no 3 n bits 72 index PRIMARY of table `test`.`tt` trx id 231106 lock_mode X(LOCK_X) locks rec but not gap(LOCK_REC_NOT_GAP)
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 32
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 0000000386c2; asc       ;;
 2: len 7; hex 2c000000410dca; asc ,   A  ;;
 3: len 4; hex 80000001; asc     ;;

RECORD LOCKS space id 127 page no 4 n bits 72 index c1 of table `test`.`tt` trx id 231106 lock mode S(LOCK_S) locks gap and rec(LOCK_ORDINARY[next_key_lock])
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;
Record lock, heap no 2 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
 0: len 4; hex 80000001; asc     ;;
 1: len 4; hex 80000001; asc     ;;

RECORD LOCKS space id 127 page no 4 n bits 72 index c1 of table `test`.`tt` trx id 231106 lock mode S(LOCK_S) locks gap before rec(LOCK_GAP)
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 4; hex 80000002; asc     ;;
  • RC
5 lock struct(s), heap size 1160, 5 row lock(s), undo log entries 2
MySQL thread id 11, OS thread handle 140737153623808, query id 316 localhost root
TABLE LOCK table `test`.`tt` trx id 231123 lock mode IX
RECORD LOCKS space id 128 page no 4 n bits 72 index c1 of table `test`.`tt` trx id 231123 lock_mode X(LOCK_X) locks rec but not gap(LOCK_REC_NOT_GAP)
Record lock, heap no 2 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
 0: len 4; hex 80000001; asc     ;;
 1: len 4; hex 80000001; asc     ;;

RECORD LOCKS space id 128 page no 3 n bits 72 index PRIMARY of table `test`.`tt` trx id 231123 lock_mode X(LOCK_X) locks rec but not gap(LOCK_REC_NOT_GAP)
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 32
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 0000000386d3; asc       ;;
 2: len 7; hex 370000003206e2; asc 7   2  ;;
 3: len 4; hex 80000001; asc     ;;

RECORD LOCKS space id 128 page no 4 n bits 72 index c1 of table `test`.`tt` trx id 231123 lock mode S(LOCK_S) locks gap and rec(LOCK_ORDINARY[next_key_lock])
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;
Record lock, heap no 2 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
 0: len 4; hex 80000001; asc     ;;
 1: len 4; hex 80000001; asc     ;;

RECORD LOCKS space id 128 page no 4 n bits 72 index c1 of table `test`.`tt` trx id 231123 lock mode S(LOCK_S) locks gap before rec(LOCK_GAP)
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 4; hex 80000002; asc     ;;

到这里RR和RC加锁并没有什么不同,因为都是唯一值,同时锁继承也都是二级索引上的都是LOCK_S|LOCK_ORDINARY[next_key_lock],但是下面就会出现不同了。

然后分析session 2的第一句:

select * from tt where c1=1 for update;

实际上这个时候存在2条c1=1的记录只有1,1标记为删除了,1,2没有提交,都是需要访问的。
然后堵塞行为为:

  • RR

LOCK WAIT 2 lock struct(s), heap size 1160, 1 row lock(s)
MySQL thread id 10, OS thread handle 140737153824512, query id 350 localhost root statistics
select * from tt where c1=1 for update
------- TRX HAS BEEN WAITING 11 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 129 page no 4 n bits 72 index c1 of table `test`.`tt` trx id 231146 lock_mode X(LOCK_X) locks gap and rec(LOCK_ORDINARY[next_key_lock]) waiting(LOCK_WAIT)
Record lock, heap no 2 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
 0: len 4; hex 80000001; asc     ;;
 1: len 4; hex 80000001; asc     ;;
  • RC
LOCK WAIT 2 lock struct(s), heap size 1160, 1 row lock(s)
MySQL thread id 10, OS thread handle 140737153824512, query id 325 localhost root statistics
select * from tt where c1=1 for update
------- TRX HAS BEEN WAITING 9 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 128 page no 4 n bits 72 index c1 of table `test`.`tt` trx id 231128 lock_mode X(LOCK_X) locks rec but not gap(LOCK_REC_NOT_GAP) waiting(LOCK_WAIT)
Record lock, heap no 2 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
 0: len 4; hex 80000001; asc     ;;
 1: len 4; hex 80000001; asc     ;;

我们这里可以看到对于RR模式下唯一键c1的1,1已经删除了。我做了debug发现这里会在函数中row_search_mvcc加锁前做判断如下:

if (!set_also_gap_locks
            || srv_locks_unsafe_for_binlog
            || trx->isolation_level <= TRX_ISO_READ_COMMITTED
            || (unique_search && !rec_get_deleted_flag(rec, comp))
            || dict_index_is_spatial(index)) {

            goto no_gap_lock;
        } else {
            lock_type = LOCK_ORDINARY;
        }

我们抛开其他来分析这两句

  • trx->isolation_level <= TRX_ISO_READ_COMMITTED
    如果是RC模式则直接上LOCK_REC_NOT_GAP及只锁住记录本身
  • (unique_search && !rec_get_deleted_flag(rec, comp))
    如果不是RC,如果是二级唯一索引并且没有被标记为del flag则标记为LOCK_REC_NOT_GAP。但是如果标记为del flag则标记为LOCK_ORDINARY就是next key lock。

分析session 1的最后一个语句也就是产生死锁的语句:

select * from tt where c1=1 for update;

如上这个语句会访问1,1标记为删除了,1,2没有提交 的两个记录。这个时候就出现了不同。

  • RC
    只需要唯一索引 1,1上 LOCK_REC_NOT_GAP|LOCK_X 及记录索引,这个锁在本事物的第一句语句上已经获得了,因此直接通过了,不需要做检测。
  • RR

需要在唯一索引 1,1上 LOCK_ORDINARY|LOCK_X 也就是就是next key lock。这个锁在本事物中并没有获取过,因此需要重新的检测所的兼容性,最终加入了等待列表。

我们来看一下函数lock_rec_lock_slow,我做debug的时候明显看到了不同的逻辑:

if (lock_rec_has_expl(mode, block, heap_no, trx)) {
 
        /* The trx already has a strong enough lock on rec: do 1,1 key lock RR NEX KEY LOCK  stronager
        nothing */
        lock_rec_print(mode,block,heap_no,index,thr_get_trx(thr));
        err = DB_SUCCESS;

    } else {

        const lock_t* wait_for = lock_rec_other_has_conflicting(
            mode, block, heap_no, trx,index);

        if (wait_for != NULL) {

            /* If another transaction has a non-gap conflicting
            request in the queue, as this transaction does not
            have a lock strong enough already granted on the
            record, we may have to wait. */

            RecLock    rec_lock(thr, index, block, heap_no, mode);

            err = rec_lock.add_to_waitq(wait_for);

        } 

三、总结

最终RR下形成了环路

  • session1 首先获得唯一索引上的 1,1记录的 LOCK_REC_NOT_GAP|LOCK_X
  • 然后session 1做update 获得唯一索引上的 1,1记录的 LOCK_ORDINARY(next key lock)|LOCK_S
  • 然后session 2需要获取唯一索引上的 1,1记录的 LOCK_ORDINARY(next key lock)|LOCK_X 发生等待
  • 然后session 1需要获取唯一索引上的 1,1记录的 LOCK_ORDINARY(next key lock)|LOCK_X 加入等待队列进行等待

死锁发生因此发生,而RC模式下最后两部需要获取的都是 LOCK_REC_NOT_GAP|LOCK_X,虽然session 2处于等待但是session因为已经获得相同级别的锁不会在进行检测加锁等待,而直接通过了。

下面是死锁的记录:


*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 117 page no 4 n bits 72 index c1 of table `t1`.`tt` trx id 230530 lock_mode X(LOCK_X) locks gap and rec(LOCK_ORDINARY[next_key_lock]) waiting(LOCK_WAIT)
Record lock, heap no 2 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
 0: len 4; hex 80000001; asc     ;;
 1: len 4; hex 80000001; asc     ;;

*** (2) TRANSACTION:
TRANSACTION 230525, ACTIVE 68 sec starting index read
mysql tables in use 1, locked 1
6 lock struct(s), heap size 1160, 6 row lock(s), undo log entries 2
MySQL thread id 6, OS thread handle 140737153423104, query id 156 localhost root statistics
select * from tt where c1=1 for update
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 117 page no 4 n bits 72 index c1 of table `t1`.`tt` trx id 230525 lock_mode X(LOCK_X) locks rec but not gap(LOCK_REC_NOT_GAP)
Record lock, heap no 2 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
 0: len 4; hex 80000001; asc     ;;
 1: len 4; hex 80000001; asc     ;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 117 page no 4 n bits 72 index c1 of table `t1`.`tt` trx id 230525 lock_mode X(LOCK_X) locks gap and rec(LOCK_ORDINARY[next_key_lock]) waiting(LOCK_WAIT)
Record lock, heap no 2 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
 0: len 4; hex 80000001; asc     ;;
 1: len 4; hex 80000001; asc     ;;

*** WE ROLL BACK TRANSACTION (1)

四、栈帧参考

最后留下几个栈帧以备分析使用

  • 锁继承
#0  lock_rec_set_nth_bit (lock=0x30b1230, i=3) at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/include/lock0priv.ic:91
#1  0x0000000001a5d44a in RecLock::lock_alloc (trx=0x7fffd7803b10, index=0x7ffe7459ff80, mode=546, rec_id=..., size=9)
    at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/lock/lock0lock.cc:1484
#2  0x0000000001a5d826 in RecLock::create (this=0x7fffec0c0eb0, trx=0x7fffd7803b10, owns_trx_mutex=false, add_to_hash=true, prdt=0x0)
    at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/lock/lock0lock.cc:1537
#3  0x0000000001a5e60c in lock_rec_add_to_queue (type_mode=546, block=0x7fff9adb8150, heap_no=3, index=0x7ffe7459ff80, trx=0x7fffd7803b10, 
    caller_owns_trx_mutex=false) at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/lock/lock0lock.cc:1853
#4  0x0000000001a611ec in lock_rec_inherit_to_gap_if_gap_lock (block=0x7fff9adb8150, heir_heap_no=3, heap_no=1)
    at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/lock/lock0lock.cc:2829
#5  0x0000000001a62ea3 in lock_update_insert (block=0x7fff9adb8150, rec=0x7fff9b9c408c "\200")
    at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/lock/lock0lock.cc:3659
#6  0x0000000001c53c25 in btr_cur_optimistic_insert (flags=0, cursor=0x7fffec0c23f0, offsets=0x7fffec0c24c8, heap=0x7fffec0c13e0, entry=0x7ffe7403bb70, 
    rec=0x7fffec0c24c0, big_rec=0x7fffec0c24b8, n_ext=0, thr=0x7ffe7403ba00, mtr=0x7fffec0c1bc0)
    at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/btr/btr0cur.cc:3346
#7  0x0000000001b195fe in row_ins_sec_index_entry_low (flags=0, mode=2, index=0x7ffe7459ff80, offsets_heap=0x7ffe7403bf98, heap=0x7ffe7403c448, entry=0x7ffe7403bb70, 
    trx_id=0, thr=0x7ffe7403ba00, dup_chk_only=false) at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/row/row0ins.cc:3166
#8  0x0000000001b1a15e in row_ins_sec_index_entry (index=0x7ffe7459ff80, entry=0x7ffe7403bb70, thr=0x7ffe7403ba00, dup_chk_only=false)
    at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/row/row0ins.cc:3421
#9  0x0000000001b9e053 in row_upd_sec_index_entry (node=0x7ffe7403b6f8, thr=0x7ffe7403ba00)
    at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/row/row0upd.cc:2337
#10 0x0000000001b9e1c3 in row_upd_sec_step (node=0x7ffe7403b6f8, thr=0x7ffe7403ba00)
    at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/row/row0upd.cc:2364     
  • RR加锁del flag记录
#0  lock_rec_set_nth_bit (lock=0x30b28b8, i=2) at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/include/lock0priv.ic:91
#1  0x0000000001a5d44a in RecLock::lock_alloc (trx=0x7fffd7804080, index=0x7ffe74064ea0, mode=259, rec_id=..., size=9)
    at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/lock/lock0lock.cc:1484
#2  0x0000000001a5d826 in RecLock::create (this=0x7fffec0c1e00, trx=0x7fffd7804080, owns_trx_mutex=true, add_to_hash=true, prdt=0x0)
    at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/lock/lock0lock.cc:1537
#3  0x0000000001a5e1c4 in RecLock::add_to_waitq (this=0x7fffec0c1e00, wait_for=0x30b0e58, prdt=0x0)
    at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/lock/lock0lock.cc:1731
#4  0x0000000001a5ee37 in lock_rec_lock_slow (impl=0, mode=3, block=0x7fff4d027b20, heap_no=2, index=0x7ffe74064ea0, thr=0x7ffe7459ff60)
    at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/lock/lock0lock.cc:2004
#5  0x0000000001a5f1ce in lock_rec_lock (impl=false, mode=3, block=0x7fff4d027b20, heap_no=2, index=0x7ffe74064ea0, thr=0x7ffe7459ff60)
    at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/lock/lock0lock.cc:2082
#6  0x0000000001a69a02 in lock_sec_rec_read_check_and_lock (flags=0, block=0x7fff4d027b20, rec=0x7fff4da8c07e "\200", index=0x7ffe74064ea0, offsets=0x7fffec0c2690, 
    mode=LOCK_X, gap_mode=0, thr=0x7ffe7459ff60) at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/lock/lock0lock.cc:6457
#7  0x0000000001b717f7 in sel_set_rec_lock (pcur=0x7ffe7459f6d0, rec=0x7fff4da8c07e "\200", index=0x7ffe74064ea0, offsets=0x7fffec0c2690, mode=3, type=0, 
    thr=0x7ffe7459ff60, mtr=0x7fffec0c2180) at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/row/row0sel.cc:1270
#8  0x0000000001b7ab6a in row_search_mvcc (buf=0x7ffe7405b9c0 "\375\002", mode=PAGE_CUR_GE, prebuilt=0x7ffe7459f4b0, match_mode=1, direction=0)
    at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/row/row0sel.cc:5591
  • RC加锁del flag记录
#0  lock_rec_lock_slow (impl=0, mode=1027, block=0x7fff3310cdf0, heap_no=2, index=0x7ffe74076d90, thr=0x7ffe7459fc20)
    at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/lock/lock0lock.cc:1962
#1  0x0000000001a5f1ce in lock_rec_lock (impl=false, mode=1027, block=0x7fff3310cdf0, heap_no=2, index=0x7ffe74076d90, thr=0x7ffe7459fc20)
    at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/lock/lock0lock.cc:2082
#2  0x0000000001a69a02 in lock_sec_rec_read_check_and_lock (flags=0, block=0x7fff3310cdf0, rec=0x7fff33bdc07e "\200", index=0x7ffe74076d90, offsets=0x7fffec0c2690, 
    mode=LOCK_X, gap_mode=1024, thr=0x7ffe7459fc20) at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/lock/lock0lock.cc:6457
#3  0x0000000001b717f7 in sel_set_rec_lock (pcur=0x7ffe7459f6d0, rec=0x7fff33bdc07e "\200", index=0x7ffe74076d90, offsets=0x7fffec0c2690, mode=3, type=1024, 
    thr=0x7ffe7459fc20, mtr=0x7fffec0c2180) at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/row/row0sel.cc:1270
#4  0x0000000001b7ab6a in row_search_mvcc (buf=0x7ffe7403ae80 "\375\002", mode=PAGE_CUR_GE, prebuilt=0x7ffe7459f4b0, match_mode=1, direction=0)
    at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/row/row0sel.cc:5591
#5  0x00000000019d5493 in ha_innobase::index_read (this=0x7ffe7403cda0, buf=0x7ffe7403ae80 "\375\002", key_ptr=0x7ffe74095600 "", key_len=5, 
    find_flag=HA_READ_KEY_EXACT) at /root/mysqlall/percona-server-locks-detail-5.7.22/storage/innobase/handler/ha_innodb.cc:9536
#6  0x0000000000f934aa in handler::index_read_map (this=0x7ffe7403cda0, buf=0x7ffe7403ae80 "\375\002", key=0x7ffe74095600 "", keypart_map=1, 
    find_flag=HA_READ_KEY_EXACT) at /root/mysqlall/percona-server-locks-detail-5.7.22/sql/handler.h:2942      
相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
SQL 关系型数据库 MySQL
MySQL事务日志-Undo Log工作原理分析
事务的持久性是交由Redo Log来保证,原子性则是交由Undo Log来保证。如果事务中的SQL执行到一半出现错误,需要把前面已经执行过的SQL撤销以达到原子性的目的,这个过程也叫做"回滚",所以Undo Log也叫回滚日志。
MySQL事务日志-Undo Log工作原理分析
|
28天前
|
关系型数据库 MySQL 数据库
mysql慢查询每日汇报与分析
通过启用慢查询日志、提取和分析慢查询日志,可以有效识别和优化数据库中的性能瓶颈。结合适当的自动化工具和优化措施,可以显著提高MySQL数据库的性能和稳定性。希望本文的详解和示例能够为数据库管理人员提供有价值的参考,帮助实现高效的数据库管理。
40 11
|
10天前
|
缓存 NoSQL 关系型数据库
MySQL原理简介—4.深入分析Buffer Pool
本文介绍了MySQL的Buffer Pool机制,包括其作用、配置方法及内部结构。Buffer Pool是MySQL用于缓存磁盘数据页的关键组件,能显著提升数据库读写性能。默认大小为128MB,可根据服务器配置调整(如32GB内存可设为2GB)。它通过free链表管理空闲缓存页,flush链表记录脏页,并用LRU链表区分冷热数据以优化淘汰策略。此外,还探讨了多Buffer Pool实例、chunk动态调整等优化并发性能的方法,以及如何通过`show engine innodb status`查看Buffer Pool状态。关键词:MySQL内存数据更新机制。
|
2月前
|
SQL 关系型数据库 MySQL
MySQL 窗口函数详解:分析性查询的强大工具
MySQL 窗口函数从 8.0 版本开始支持,提供了一种灵活的方式处理 SQL 查询中的数据。无需分组即可对行集进行分析,常用于计算排名、累计和、移动平均值等。基本语法包括 `function_name([arguments]) OVER ([PARTITION BY columns] [ORDER BY columns] [frame_clause])`,常见函数有 `ROW_NUMBER()`, `RANK()`, `DENSE_RANK()`, `SUM()`, `AVG()` 等。窗口框架定义了计算聚合值时应包含的行。适用于复杂数据操作和分析报告。
126 11
|
2月前
|
存储 关系型数据库 MySQL
从新手到高手:彻底掌握MySQL表死锁
通过本文的介绍,希望你能深入理解MySQL表死锁的概念、原因、检测方法及解决方案,并在实际开发中灵活应用这些知识,提升系统的稳定性和性能。
405 9
|
3月前
|
SQL 算法 关系型数据库
面试:什么是死锁,如何避免或解决死锁;MySQL中的死锁现象,MySQL死锁如何解决
面试:什么是死锁,死锁产生的四个必要条件,如何避免或解决死锁;数据库锁,锁分类,控制事务;MySQL中的死锁现象,MySQL死锁如何解决
|
4月前
|
关系型数据库 MySQL 数据库
一个 MySQL 数据库死锁的案例和解决方案
本文介绍了一个 MySQL 数据库死锁的案例和解决方案。
328 3
|
4月前
|
存储 关系型数据库 MySQL
基于案例分析 MySQL 权限认证中的具体优先原则
【10月更文挑战第26天】本文通过具体案例分析了MySQL权限认证中的优先原则,包括全局权限、数据库级别权限和表级别权限的设置与优先级。全局权限优先于数据库级别权限,后者又优先于表级别权限。在权限冲突时,更严格的权限将被优先执行,确保数据库的安全性与资源合理分配。
|
4月前
|
SQL 关系型数据库 MySQL
京东面试:什么情况下 mysql RR不能解决幻读? RR隔离mysql如何实现?
老架构师尼恩在其读者交流群中分享了关于MySQL事务隔离级别的深入解析,特别针对RR级隔离如何解决幻读问题进行了详细讨论。文章不仅解释了ACID中的隔离性概念,还列举了四种事务隔离级别(未提交读、提交读、可重复读、串行读)的特点及应用场景。尼恩通过具体的例子和图表,清晰地展示了不同隔离级别下的并发事务问题(脏读、不可重复读、幻读)及其解决方案,特别是RR级隔离下的MVCC机制如何通过快照读和当前读来防止幻读。此外,尼恩还提供了相关面试题的解答技巧和参考资料,帮助读者更好地准备技术面试。更多详细内容和实战案例可在《尼恩Java面试宝典》中找到。
|
4月前
|
存储 关系型数据库 MySQL
RR隔离mysql如何实现?什么情况RR不能解决幻读?
【10月更文挑战第9天】在数据库事务中,隔离级别是一个重要的概念,它定义了事务在并发环境下如何相互隔离。MySQL支持四种隔离级别:READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。其中,REPEATABLE READ(简称RR)是MySQL的默认隔离级别,它旨在解决脏读、不可重复读和幻读问题。
161 2

推荐镜像

更多