美文网首页
MySQL:master线程统计/RW-LOCK统计/page分

MySQL:master线程统计/RW-LOCK统计/page分

作者: 重庆八怪 | 来源:发表于2021-09-07 17:52 被阅读0次

    一、问题来源

    问1 ,为啥5.7的这个值为0


    image.png

    问2:为啥8.0的这个值为0

    image.png

    二、关于RW LOCK

    其实Innodb中并发控制结构分为rw lock,mutex(TTASEventMutex)和event(带有条件变量),主要作为Innodb的并发访问控制,这部分非常复杂,还需要学习,我们通常在show engine innodb中看到的mutex或者rw lock就是他们。比如:

    • rw lock其中一个作用就是作为buffer page(BPageLock)的保护,通常用于page的并发访问,比如修改和读取buffer page需要上不同的锁。
    • mutex其中一个作用就是作为buffer block(BPageMutex 类型为TTASEventMutex)的保护,比如需要修改/访问 block io fix部分则需要加这个锁。

    rw lock和mutex(TTASEventMutex)都会接受参数的控制:

    | innodb_spin_wait_delay             | 6     |
    | innodb_sync_spin_loops             | 30    |
    

    逻辑大概如下:

    rw_lock_s_lock_spin 函数
    如果第一次获取失败
      开启spin获取,则spins+1
        一层循环开启:
          二层循环,循环次数为srv_n_spin_wait_rounds(sync_spin_loops)
            等待每次等待时长srv_spin_wait_delay(大概为空循环的次数默认为6(srv_spin_wait_delay)*50(srv_spin_wait_pause_multiplier) 300次)
            如果获取了lock的使用权则结束二层循环
            否则需要等满srv_n_spin_wait_rounds
          如果等待满srv_n_spin_wait_rounds,则归还
          CPU给操作系统,等待下次CPU的调度
          再次调度的时候,rounds+1
          再次尝试获取锁资源如果获取成功,则退出一层循环
          如果获取锁资源如果获取失败,则OS waits+1,且进入muext等待
          ->sync_array_wait_event(sync_arr, cell); //等待唤醒,唤醒后继续判断,存在多个线程同时竞争的情况
          唤醒后再次循环二层循环,尝试获取锁资源      
        一层继续循环
    

    sync_spin_loops的内部定义为srv_n_spin_wait_rounds
    如果我们将经历srv_n_spin_wait_rounds*srv_spin_wait_delay*srv_spin_wait_pause_multiplier:
    默认为30*6*50=9000(代码中)
    看做一轮等待。那么从逻辑来看定义如下:

    • spins代表是spin获取的次数,如果第一次就获取成功了则这里是为0的
    • rounds代表是经历多少轮数才获取到lock的使用权。当然最后一轮可能提前获取到使用权。
    • OS waits代表是经历了多少轮的等待才获取了lock的使用权。

    那么有如下结论

    • spins越少越好,代表第一次获取成功了
    • OS waits大量少于rounds越好,代表偶虽然第一次获取失败,但是第spin一次就获取成功了

    但是myql 5.7中spins中关于x lock和s lock 对于这个计数是没有做的,8.0.23有计数。所以5.7这里可能是0。

    并且注意这里是RW-LATCH INFO因此mutex是不包含的。

    三、关于8.0 master线程的简析

    master线程主要是每秒醒来干活,包含:

    • changer buffer 合并
    • flush redo
    • 唤醒purge线程干活
    • checkpoint(8.0剥离成了单独的checkpoint线程)

    但是其中包含active和idle的方式,其判断主要是arcive计数器和上次是否相同,不相同则是active方式。那么我看了一下如下情况会进入active方式:

    • 事务提交一次,增加一次active计数。
    • update/delete/insert 总数超过了2的32次方就增加一次active计数。
    • 出现rollback,每行记录都会触发增加一次active计数。
    • innodb关闭表,增加一次active计数。

    我们实际上可以从这个信息大概可以看出数据库数据的繁忙程度。但是在8.0中全局变量srv_log_writes_and_flush并没有做任何修改,因此初始化为0它一值都是0。5.6 5.7是有修改的,但是值没有什么意义就是 srv_active+ srv_idle,代表master线程触发的写盘操作。

    四、page分配内存

    (buf_page_get_gen->buf_buddy_alloc_low)

    1. 首先从freelist中获取块,不能获取则转下一个逻辑
    2. 从LRU中获取,受到参数innodb_lru_scan_depth的影响表示每次检查的块的数量,其中有一些条件不能获取
      • 块本生是脏块
      • 块本生被io fix了
        如果获取成功将从hash table中去掉,并且从lru放到free list中如果循环完整个LRU链表都不能获取则转下一个逻辑
    3. 如果扫描了整个LRU都不能获取,那么说明块可能脏块比较多了进行单块刷盘,这个时候是直接fsync了(buf_flush_single_page_from_LRU)

    其他:

    8.0.23
        mutex_enter(&buf_pool->flush_state_mutex); //为TTASEventMutex
    
          os_event_reset(buf_pool->no_flush[flush_type]); //为os_event  不受spin参数影响,例子https://www.jianshu.com/p/24b212286a1b
    
    

    那么研究方向应该是TTASEventMutex\rw lock\os_event 各自的实现

    相关文章

      网友评论

          本文标题:MySQL:master线程统计/RW-LOCK统计/page分

          本文链接:https://www.haomeiwen.com/subject/qnlpwltx.html