mysql semaphore waits_MySQL InnoDB中的争用:Semaphores章节中有用的信息

在高并发的世界中,越来越多的用户-连接-线程,进而导致了争用。但是我们如何轻松确定争用点?

先前已经讨论了不同的方法,类似使用 Perf

和火焰图来追踪函数调用花费的时间是否超过预期。这个方法很棒,但是有没有更常用的方法,例如MySQL客户端?让我们看看 SHOW ENGINE INNODB STATUS

命令输出中的SEMAPHORES章节。

信号量信号量章节显示了与InnoDB等待相关的所有指标。如果您有很高的并发工作量,这一章节是您的好朋友。简而言之,它包含2类数据:事件计数器和当前等待的列表。

当前等待这部分应该为空,除非MySQL有很高并发,导致InnoDB开始使用等待机制。如果你没有看到“--Thread was waited”,说明没有争用。

它是什么样子的?它可能是这样的:----------

SEMAPHORES

----------

OS WAIT ARRAY INFO:reservation count1744351

--Thread139964395677440has waited at btr0cur.cc line5889for0seconds the semaphore:

S-lockon RW-latch at0x7f4c3d73c150createdinfile buf0buf.cc line1433

a writer(thread id139964175062784)has reserved itinmode exclusive

number of readers0,waiters flag1,lock_word:0

Lasttime read lockedinfile btr0sea.cc line1121

Lasttime write lockedinfile/mnt/workspace/percona-server-5.7-redhat-binary-rocks-new/label_exp/min-centos-7-x64/test/rpmbuild/BUILD/percona-server-5.7.28-31/percona-server-5.7.28-31/storage/innobase/btr/btr0sea.cc line1121

OS WAIT ARRAY INFO:signal count1483499

RW-shared spins0,rounds314940,OS waits77827

RW-excl spins0,rounds205078,OS waits7540

RW-sx spins4357,rounds47820,OS waits949

Spinrounds per wait:314940.00RW-shared,205078.00RW-excl,10.98RW-sx或者类似这样----------

SEMAPHORES

----------

OS WAIT ARRAY INFO:reservation count1744302

--Thread139964401002240has waited at row0ins.cc line2520for0seconds the semaphore:

X-lock(wait_ex)on RW-latch at0x7f4c3d956890createdinfile buf0buf.cc line1433

a writer(thread id139964401002240)has reserved itinmode wait exclusive

number of readers1,waiters flag0,lock_word:ffffffffffffffff

Lasttime read lockedinfile row0sel.cc line3869

Lasttime write lockedinfile/mnt/workspace/percona-server-5.7-redhat-binary-rocks-new/label_exp/min-centos-7-x64/test/rpmbuild/BUILD/percona-server-5.7.28-31/percona-server-5.7.28-31/storage/innobase/row/row0upd.cc line2881

OS WAIT ARRAY INFO:signal count1483459

RW-shared spins0,rounds314905,OS waits77813

RW-excl spins0,rounds204982,OS waits7532

RW-sx spins4357,rounds47820,OS waits949

Spinrounds per wait:314905.00RW-shared,204982.00RW-excl,10.98RW-sx或者难以置信的长度(这里没有显示)

监控特定部分的方式是通过执行一个无限循环:whiletrue;domysql-N-e"show engine innodb status\G"|sed-n'/SEMAPHORES/,/TRANSACTIONS/p';sleep1;done但是您应该如何处理该信息?

寻找信息从当前的等待中,我们需要以下内容:MySQL确切的版本(和分支,Percona Server,Oracle‘s MySQL,还是MariaDB)

文件名

文件行数

让我们看第一个示例,从PMM看这是一个经历了一段时间高并发的服务器:

d0156e5c1750e46a1d6ac27d0c31425d.png有人说:“这最高峰只有42个线程,大多数的吞吐量分布在低并发的时候!”这是一个2核的VM,物理内存很小,因此缓冲池也很小。平均运行22个线程已经是高并发。

从第一个示例的信号量输出,我们可以看到:--Thread139964395677440has waited at btr0cur.cc line5889for0seconds the semaphore:

S-lockon RW-latch at0x7f4c3d73c150createdinfile buf0buf.cc line1433

a writer(thread id139964175062784)has reserved itinmode exclusive number of readers0,waiters flag1,lock_word:0

Lasttime read lockedinfile btr0sea.cc line1121

Lasttime write lockedinfile/mnt/workspace/percona-server-5.7-redhat-binary-rocks-new/label_exp/min-centos-7-x64/test/rpmbuild/BUILD/percona-server-5.7.28-31/percona-server-5.7.28-31/storage/innobase/btr/btr0sea.cc line1121MySQL的版本是什么?最后一行告诉我们:Percona Server-5.7.28-31

文件是什么?在第几行?btr0cur.cc的第5889行在等待buf0buf.cc的1433行创建的RW-latch的S-Lock,但是另一个线程在btr0sea.cc的第1121行的独占锁。

现在我们有了方向。让我们看看里面有什么。

深入了解源码我需要下载源码来查看吗?不,您不需要!您需要访问代码源,本例中是GitHub 源。

这就是准确版本派上用场的地方。为了保证我们读取的是正确的行的代码,我们最好确保读的是正确的版本。

在源中查找Github易于浏览,在本例中,我们需要查看的是5.7.28-31版本。Percona Server源的URL是:https://github.com/percona/percona-server/.

点击链接,我们需要找到相应的版本。

查找相应的版本可以在下图所示的链接中找到版本

59ef6a520b63825d9523f0994b720241.png在里面可以看到具体版本:

6646366711e19569fff7bb1059d2dbb1.png

单击该链接,您可以看到具体的标签:

eb984ec19f4459bd17c9867eaebe6b45.png

最后,点击上面显示的链接,您将进入所需版本的源:https://github.com/percona/percona-server/tree/Percona-Server-5.7.28-31

接下来我们将读取文件的实际内容。

浏览代码树代码的树形结构为:

-root

---storage

-----innobase

InnoDB存储引擎源码在“innobase”目录中。在该目录中,还有许多其他的目录。但是如何选择正确的呢?答案是文件名。我们需要查看的文件有:btr0cur.cc

btr0sea.cc

buf0buf.cc

所有的文件都有相同的语法:xxx0xxx.xx,并且目录名是0之前的部分。在本例中,我们只需要查看2个文件夹:btr和buf。在目录里,查找文件就很容易了。

这是提到的文件的行号:https://github.com/percona/percona-server/blob/Percona-Server-5.7.28-31/storage/innobase/btr/btr0sea.cc#L1121

https://github.com/percona/percona-server/blob/Percona-Server-5.7.28-31/storage/innobase/buf/buf0buf.cc#L1433

https://github.com/percona/percona-server/blob/Percona-Server-5.7.28-31/storage/innobase/btr/btr0cur.cc#L5889

如文件头所述,btr0sea.cc文件是“索引树自适应搜索”,又称:自适应哈希索引(AHI)

buf0buf.cc文件是“数据库缓冲池”,又称:InnoDB缓冲池

btr0cur.cc文件是“索引树游标”,又称:实际的B+树或者数据在InnoDB中存储的位置。

接下来如何做?在btr0cur.cc文件的5889行,InnoDB有一个btr_estimate_n_rows_in_range_low函数,在文档中的描述为索引范围扫描估算的行数,实际的内容为:btr_cur_search_to_nth_level(index,0,tuple1,mode1,

BTR_SEARCH_LEAF|BTR_ESTIMATE,

&cursor,0,

__FILE__,__LINE__,&mtr);那么什么是btr_cur_search_to_nth_level?在同一文件中,我们找到其定义,它的描述为在给定级别扫描索引树和位置的树光标。基本上,它是在寻找一个行值。但是这个操作被阻塞了,因为它需要一个共享资源,在本例中,是缓冲池:

在buf0buf.cc的文件1433行,缓冲池试图在一个块上创建一个锁rw_lock_create(PFS_NOT_INSTRUMENTED,&block->lock,SYNC_LEVEL_VARYING);该操作发生在名为buf_block_init的函数中(可以在代码中向上查找到它),描述为在创建buf_pool时初始化缓冲区控制块。这实际上是在innodb_buffer_pool_size修改后创建缓冲池空间,并被延迟。

在btr0sea.cc文件的1121行,操作如下:if(!buf_page_get_known_nowait(

latch_mode,block,BUF_MAKE_YOUNG,

__FILE__,__LINE__,mtr)){该行位于函数btr_search_guess_on_hash内部,被描述为尝试根据索引的哈希搜索信息来猜测正确的搜索位置。因此,它使用的的是AHI中的信息。buf_page_get_known_nowait定义为当无法进行等待时,使用它来访问一个已知的数据库页面,这几乎是不言自明的。

那这里有什么?AHI的争用!这是问题点吗?让我们回到当时场景:--Thread139964395677440has waited at btr0cur.cc line5889for0seconds the semaphore:这意味着它已经等待了0秒。在这个场景下,争用很快消失。此外,还有一些非常重要的注意事项:这个争用在监控期间仅出现一次。这意味着它不是一个长期的问题,属于“没有问题”的范畴。它发生了一次,速度很快。

但是,它经常发生怎么办?您应该增加缓冲池大小,增加AHI分区数量,甚至完全禁用AHI。当然,这三个方法都需要测试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值