声明:本博客所有文章均为博主原创,请勿非法复制。请勿盗取原创图片。
1.内存管理
- 1.需要经常找free数据块; free list(free链)
- 2.需要经常找冷的数据块; lru list(最近最少使用链)
- 3.就需要系统将这些logfile对应的脏块,写入到磁盘上。flush list(按照脏的早晚链起来的链)
默认2个logfile,每个20M。logfile小了,容易hang住。
一个数据库最基本的调整
- 增加组数;
- 增加logfile大小;
- 增加写线程的数量。
需要3种链(chain)
一种链一种作用。
一个个体可以在多个链上。
(比如同是一个班的学生,1.按高矮链起来 2.按男女链起来…)
对于链来说,我们需要进行遍历。
为什么要引入free,lru,flush list三种链
内存管理:
读线程将数据页从磁盘中调入内存之中时,会首先寻找free数据块,如果有free数据块,就将新来的数据放入free数据块中;如果没有free,就会寻找冷数据块,放入冷数据块中。而存储中的logfile文件也存在着轮转覆盖,假如有两个logfile文件,第一个写满后会写第二个,第二个写满后会重新覆盖第一个,这时候如果第一个logfile中对应的脏块还没有写完,就会先将脏块写入到磁盘之中再覆盖,首先要将较早脏的数据块写入到磁盘之中,这时候就会有问题,系统怎么知道哪个是free数据块,那些是冷数据块,那些是较早脏的快。这时候就引入了free list,lru list,flush list。
mysql中用链的形式把数据块穿起来。
- freelist就能够free块穿起来,当寻找free块时,就按照某种顺序来将新来的数据写入到free数据块中。
- lru list就是将冷数据块连接起来,按照某种顺序将新来的数据覆盖上去
- flush list原理相同,通过链把脏数据按照某种顺序(比如最早脏的在最左边)将脏数据连接起来,方便写入。
锁,用来管理对共享文件的并发访问
锁的类型
- latch称为栓锁(轻量级的锁),因为其要求锁的时间非常短。
- 在innodb存储引擎中,又可以分为mutex(互斥量)和rwlock(读写锁)。其目的是用来保证并发线程操作临街资源的正确性,并且通常没有死锁检测的机制。
- 而lock锁的对象是事务,用来锁定数据库的对象,如表、页、行。并且一般lock的对象仅在事务commit或者rollback后释放(不同事务的隔离级别释放的时间可能不一样)。有死锁机制。
链上是有锁的。latch 锁。
例子:
线程1持有latch,对free list正在进行遍历;
线程2也想持有latch,对free list进行遍历;
结果,线程2被阻塞。
线程的三种状态
- gets:获取latch
- misses:获取latch失败了
- sleeps:执行空代码,显得很忙。
都伴随着latch的征用。
latch争用的表现
- 1.latch争用会表现为cpu繁忙;
- 2.latch争用没有排队。
latch(锁)争用的原因
- 1.内存访问频繁;
- 2.list 太长了。
latch争用的过程
首先链上是有锁的,这个锁叫latch,当一个线程持有latch时(也就是对这个链进行操作的时候),其他的线程得在一边看着。比如线程1持有latch,正在对freelist进行遍历,线程2也想进行遍历,是不可能的,所以现在线程2阻塞,只有两种选择,一是退出,二是等待,但如果等待就会占用cpu,如果想占用cpu就要有事可做,否则cpu会把没事做的线程踢出去,所以线程2就会执行某段空代码来让自己忙起来(所以虽然线程2在等待,但cpu还是忙碌的),这时候线程2会有三种情况:gets,misses,sleeps。gets就是随机的去看看freelist是否已经可以遍历,misses就是线程2错过了freelist可遍历时间,被线程3抢走了,只能重新等待,sleeps就是misses的太多了,受不了了,不执行空代码乖乖的退出了。
- latch争用过程中,会表现的cpu繁忙
- latch争用没有排队
- latch争用比较严重时,要调整innodb_buffer_pool中instance的数量,
- instance数量多了,每个instance中数据就少了,链也就短了。
- latch争用繁忙时,内存被频繁的访问,因为链在内存之中。
- 对于访问不是很频繁,同时相对较短的链,用mutex来保护而不用latch,因为mutex更为简单,占用空间小。
latch争用常用监控指标
RW-shared spins 0, rounds 16, OS waits 8
RW-excl spins 0, rounds 0, OS waits 0
RW-sx spins 0, rounds 0, OS waits 0
Spin rounds per wait:16.00 RW-shared, 0.00 RW-excl, 0.00 RW-sx
这几个数据是看latch与mutex的争用成都如果过高
需要优化mysql,降低对内存读的数量(很重要)。
mutex 互斥锁
操作系统的mutex 的特点:
- 小;通过os申请,不占用自己的内存。
mysql>show engine innodb status \G
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 2, signal count 2
Mutex spin waits 0, rounds 0, OS waits 0
RW-shared spins 2, rounds 60, OS waits 2
RW-excl spins 0, rounds 0, OS waits 0
Spin rounds per wait: 0.00 mutex, 30.00 RW-shared, 0.00 RW-excl
--------
- oswaits:sleep的时间
- innodb在获得mutex时是两阶段的。如果Mutex被人锁住了,那么它不会像教科书里面的那样,直接就sleep等待被唤醒了。而是先做一个循环,不断去获得mutex锁,称之为spin-wait,然后才sleep。因为sleep等待被唤醒的代价还是比较高的。通过spin-wait,可以明显降低这个开销。
- mutex spin waits 这个代表的是线程获得的锁,但是被别人锁住了,所以它得首先spin-wait;
- rounds:是线程在spin-wait循环检查mutex是否已经释放的探测次数;
- OS waits:是spin-wait完成以后,还是没有获得mutex,不得不sleep的次数。这个主要是评估mutex获取不到的比例。比如:
- 请求mutex不到的情况是 mutex spin waits的数,但是经过spin-wait,实际上只有OS waits的次数,也就是说,中间的差值,就是稍微等一下就能拿到mutex。
mutex:排斥。
spin:旋转。
rounds:旋转一周是1round;
os waits:就是sleep,被踢出去了;
第二行是:以共享的形式访问的时候的统计;
第三行是:以排他的形式访问的时候的统计。
如何降低latch争用
- 对访问不是很频繁,同时相对较短的链,我们使用mutex就可以来保护这些链。
- 所以,对于访问频繁的链,(会有大量的读和写),还是要用latch来进行保护。
- mutex可以理解为排他的latch。
- mutex只能写编号。
解决方案:
- 1.优化SQL,降低对内存读的数量;
- 2.增加instances的数量。
关于LRU链表
Innodb存储引擎对传统的LRU(Least Recently Used 最近最少使用)算法做了优化,LRU列表中加入了midpoint位置。新读取到的页,虽然是最新访问的页,但并不是直接放入到LRU列表的首部,而是放入到LRU列表的midpoint位置。
这个算法在InnoDB存储引擎下称为 midpoint inserttion strategy。在默认配置下,该位置在LRU列表长度的5/8处。
midpoint位置可由参数 innodb_old_blocks_pct 控制,eg:
mysql>show variables like 'innodb_old_blocks_pct'\G;