Skip to content

SEMAPHORES

xiaoboluo768 edited this page Jun 13, 2020 · 4 revisions
  • 第三段信息部分
    • 如果有高并发的工作负载,你就要关注下接下来的段(SEMAPHORES信号量),它包含了两种数据:事件计数器以及可选的当前等待线程的列表,如果有性能上的瓶颈,可以使用这些信息来找出瓶颈,不幸的是,想知道怎么使用这些信息还是有一点复杂,下面先给出一些解释:
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 68581015, signal count 218437328 
--Thread 140653057947392 has waited at btr0pcur.c line 437 for 0.00 seconds the semaphore:
S-lock on RW-latch at 0x7ff536c7d3c0 created in file buf0buf.c line 916
a writer (thread id 140653057947392) has reserved it in mode  exclusive
number of readers 0, waiters flag 1, lock_word: 0
Last time read locked in file row0sel.c line 3097
Last time write locked in file /usr/local/src/soft/mysql-5.5.24/storage/innobase/buf/buf0buf.c line 3151
--Thread 140653677291264 has waited at btr0pcur.c line 437 for 0.00 seconds the semaphore:
S-lock on RW-latch at 0x7ff53945b240 created in file buf0buf.c line 916
a writer (thread id 140653677291264) has reserved it in mode  exclusive
number of readers 0, waiters flag 1, lock_word: 0
Last time read locked in file row0sel.c line 3097
Last time write locked in file /usr/local/src/soft/mysql-5.5.24/storage/innobase/buf/buf0buf.c line 3151
Mutex spin waits 1157217380, rounds 1783981614, OS waits 10610359
RW-shared spins 103830012, rounds 1982690277, OS waits 52051891
RW-excl spins 43730722, rounds 602114981, OS waits 3495769
Spin rounds per wait: 1.54 mutex, 19.10 RW-shared, 13.77 RW-excl

# 内容比较多,下面分段依次解释:
OS WAIT ARRAY INFO: reservation count 68581015, signal count 218437328  #这行给出了关于操作系统等待数组的信息,\
它是一个插槽数组,innodb在数组里为信号量保留了一些插槽,操作系统用这些信号量给线程发送信号,使线程可以继续运行,\
以完成它们等着做的事情,这一行还显示出innodb使用了多少次操作系统的等待:保留统计(reservation count)显示了\
innodb分配插槽的频度,而信号计数(signal count)衡量的是线程通过数组得到信号的频度,操作系统的等待相对于\
空转等待(spin wait)要昂贵些。

--Thread 140653057947392 has waited at btr0pcur.c line 437 for 0.00 seconds the semaphore:
S-lock on RW-latch at 0x7ff536c7d3c0 created in file buf0buf.c line 916
a writer (thread id 140653057947392) has reserved it in mode  exclusive
number of readers 0, waiters flag 1, lock_word: 0
Last time read locked in file row0sel.c line 3097
Last time write locked in file /usr/local/src/soft/mysql-5.5.24/storage/innobase/buf/buf0buf.c line 3151
--Thread 140653677291264 has waited at btr0pcur.c line 437 for 0.00 seconds the semaphore:
S-lock on RW-latch at 0x7ff53945b240 created in file buf0buf.c line 916
a writer (thread id 140653677291264) has reserved it in mode  exclusive
number of readers 0, waiters flag 1, lock_word: 0
Last time read locked in file row0sel.c line 3097
Last time write locked in file /usr/local/src/soft/mysql-5.5.24/storage/innobase/buf/buf0buf.c line 3151

# 这部分显示的是当前正在等待互斥量的innodb线程,在这里可以看到有两个线程正在等待,每一个都是以--Thread <数字> has waited...开始,\
这一段内容在正常情况下应该是空的(即查看的时候没有这部分内容),除非服务器运行着高并发的工作负载,促使innodb采取让操作系统等待的措施,\
除非你对innodb源码熟悉,否则这里看到的最有用的信息就是发生线程等待的代码文件名 /usr/local/src/soft/mysql-5.5.24/storage/innobase/buf/buf0buf.c line 3151。

# 在innodb内部哪里才是热点?举例来说,如果看到许多线程都在一个名为buf0buf.c的文件上等待,那就意味着你的系统里存在着缓冲池竞争,\
这个输出信息还显示了这些线程等待了多少时间,其中waiters flag显示了有多少个等待着正在等待同一个互斥量。 如果waiters flag为0\
那就表示没有线程在等待同一个互斥量(此时在waiters flag 0后面可能可以看到wait is ending,表示这个互斥量已经被释放了,\
但操作系统还没有把线程调度过来运行)。

# 你可能想知道innodb真正等待的是什么,innodb使用了互斥量和信号量来保护代码的临界区,如:限定每次只能有一个线程进入临界区,\
或者是当有活动的读时,就限制写入等。在innodb代码里有很多临界区,在合适的条件下,它们都可能出现在那里,常常能见到的一种情形是:\
获取缓冲池分页的访问权的时候。

# 在等待线程之后的部分信息如下,这部分显示了更多的事件计数器,在每一个情形中,都能看到innodb依靠操作系统等待的频度:
Mutex spin waits 1157217380, rounds 1783981614, OS waits 10610359 #这行显示的是跟互斥量相关的几个计数器
RW-shared spins 103830012, rounds 1982690277, OS waits 52051891 #这行显示读写的共享锁的计数器
RW-excl spins 43730722, rounds 602114981, OS waits 3495769 #这行显示读写的排他锁的计数器
Spin rounds per wait: 1.54 mutex, 19.10 RW-shared, 13.77 RW-excl

# innodb有着一个多阶段等待的策略,首先,它会试着对锁进行空转等待,如果经历了一个预设的空转等待周期\
(设置innodb_sync_spin_loops配置变量命令)之后还没有成功,那就会退到更昂贵更复杂的等待数组中。空转等待的成本相对较低,\
但是它们要不停地检查一个资源能否被锁定,这种方式会消耗CPU周期,但是,这没有听起来那么糟糕,因为当处理器在等待IO时,\
一般都有一些空闲的CPU周期可用,即使是没有空闲的CPU周期,空等也要比其他方式更加廉价一些。然而,当另外一个线程能做一些事情的时候,\
空转等待也还会把CPU独占着。空转等待的替代方案就是让操作系统做上下文切换,这样,当一个线程在等待时,另外一个线程就可以被运行,\
然后,通过等待数组里的信号量发出信号,唤醒那个沉睡的线程,通过信号量来发送信号是比较有效的,但是上下文切换就很昂贵,\
这很快就会积少成多,每秒钟几千次的切换会引发大量的系统开销。

# 你可以通过修改innodb_sync_spin_loops的值,试着在空转等待与操作系统等待之间达成平衡,不要担心空转等待,除非你在一秒里看到\
几十万个空转等待。此时,你可以考虑performance_schema库或者show engine innodb mutex;查看下相关信息。
  • PS:如果出现大量等待信号量的线程,需要引起足够重视,可能是由于磁盘I/O性能不足或InnoDB引起内部资源争用问题的导致(争用可能是由于并发查询量过大或操作系统线程调度问题)。通过增大系统配置变量innodb_thread_concurrency的值可能会有所帮助,如果需要查询互斥量信息,可以通过SHOW ENGINE INNODB MUTEX语句查看。

上一篇:BACKGROUND THREAD | 下一篇:LATEST FOREIGN KEY ERROR

Clone this wiki locally