zoukankan      html  css  js  c++  java
  • 29 如何判断一个数据库是不是出了问题

    29 如何判断一个数据库是不是出了问题

    在主备环境中,必不可少的是出现主从的切换,一种是主动切换,一种是被动切换,往往是因为主库出了问题,由HA系统发起的。

    怎么判断一个主库出现了问题了呢

    select 1 判断

    实际上,select 1成功返回,只能说明这个库的进程还在,并不能说明主库没问题,下面一个场景

    set global innodb_thread_concurrency=3;

    CREATE TABLE `t` (

      `id` int(11) NOT NULL,

      `c` int(11) DEFAULT NULL,

      PRIMARY KEY (`id`)

    ) ENGINE=InnoDB;

     insert into t values(1,1)

    SESSION A

    SESSION B

    SESSION C

    SESSION D

    select sleep(100) from t;

    select sleep(100) from t;

    select sleep(100) from t;

    select 1;(query ok)

    select *from t;

    (blocked)

    这里设置innodb_thread_concurrency参数的目的是,控制innodb的并发线程上限,也就是说,一旦并发线程达到这个值,innodb在接收到请请求的时候,就会进入等待状态,直到有线程退出。

    这里设置为3,表示innodb只允许3个线程并行执行,前3个都是sleep(100),使得这3个语句都处于”执行状态”,依次来模拟大查询,在session d里面,select 1 是成功的,但是查询表t 却被堵塞了,就是说,这时候用select 1来检测数据库是否正常的话,是检测不出问题的。

    innodb中,innodb_thread_concurrency这个参数的值默认是0,表示不限制并发线程数量,但是,不限制是肯定不行的,因为,一个机器的cpu核数有限,线程全冲进来,上下文切换的成本就会太高。

    通常我们建议,把这个参数设置为64-128之间,也就是64-128个并发线程,这里区分并发线程和并发连接

    show processlist中,看到的是连接,并发连接,”当前正在执行”的语句,才是这里的并发查询

    并发连接数达到几千个影响并不大,就是多占一些内存而已,而并发查询高才是cpu的杀手,这就是要限制这个参数的原因。

    实际上,在现成计入锁等待以后,并发线程的计数就会减1,也就是说等行锁(包括间隙锁)的线程是不算在这128个线程里面的。

    查表判断

    为了能够检测innodb并发线程数过多导致的系统不可用情况,我们需要访问innodb的场景,一般做法是在系统库(mysql)里创建一个表,里面只放一行数据,然后定期执行;

    select *from mysql.health_check

    使用这个方法,可以检测出由于并发线程数过多导致的数据库不可用的情况。

    但是又会碰到另外的一个问题,即空间满了以后,当更新事务要写binlog,一旦binlog所在的磁盘的空间占用率达到100%,那么所有的更新语句和事务提交的commit语句就会被堵住,但是,这时候系统时可以正常查询

    更新判断

    常见做法是放一个timestamp字段,来表示更新执行检测的时间。

    update mysql.health_check set t_modified=now();

    节点可用性的检测应该包含主库和备库,如果用更新来检查主库,那么备库也要更新检测

     CREATE TABLE `health_check` (

      `id` int(11) NOT NULL,

      `t_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,

      PRIMARY KEY (`id`)

    ) ENGINE=InnoDB;

    /* 检测命令 */

    insert into mysql.health_check(id, t_modified) values (@@server_id, now()) on duplicate key update t_modified=now();

    更新判断是一个比较常用的方案,不过依然存在一些问题,其中,判断慢这个问题不好处理,更新语句,如果失败或者超时时,就可以发起主备切换,为什么还要判断慢的问题呢

    这里涉及到服务器IO资源分配的问题。

    首先,所有的检测逻辑都需要一个超时时间N,执行一条update语句,超过N秒后还不返还,就认为系统不可用

    当一个日子盘的io利用率已经是100%的场景,这时候,整个系统响应就比较慢,已经需要做主备切换了。

    但是要知道,io利用率100%表示系统的io是在工作的,每个请求都有机会获得io资源,执行自己的任务,而我们的检测使用的update命令,需要的资源很少,所以可能在拿到io资源的时候就可以提交成功,并且在超时时间n秒未达到就返回检测系统

    检测系统一看,update命令没有超时,就得出系统时正常的结论。

    上面说的都是基于外部的检测,随机性。

    内部统计

    针对磁盘利用率这个问题,如果mysql可以告诉我们,内部每一次io请求时间,就可以判断数据是否出问题的方法就可靠

    mysql 5.6版本,提供了performance_schema库,表

    performance_schema.file_summary_by_event_name 表里统计了每次io请求的时间

    event_name='wait/io/file/innodb/innodb_log_file'

    图中这一行表示统计的是redo log的写入时间,event_name表示统计类型

    接下来的三组数据,显示的是redo log操作的时间统计

    COUNT_STAR所有io的总次数,单位皮秒,SUMMINAVGMAX,总和,最小值,平均值,最大值

    COUNT_READ 读操作

    COUNT_WRITE 写操作

    COUNT_MISC 对其他类型数据的统计,在redo log里,可以认为就是对fsync的统计

    表里binlog对应的是event_name=’wait/io/file/sql/binlog’这一行

    因为每一次操作数据,performance_schema都需要额外的统计这些信息,所以打开这个功能是有损耗的

    如果打开所有的performance_schema选项,性能大概会下降10%左右。

    需要打开redo log的时间监控

    mysql> update setup_instruments set ENABLED='YES', Timed='YES' where name like '%wait/io/file/innodb/innodb_log_file%';

    假设已经开启 redo logbinlog的统计信息,可以通过MAX_TIMER的值来判断数据库是否出现了问题,可以设定一个阈值,单次请求超过200毫秒就属于异常

    select event_name,MAX_TIMER_WAIT  FROM performance_schema.file_summary_by_event_name

    where event_name in ('wait/io/file/innodb/innodb_log_file','wait/io/file/sql/binlog') and MAX_TIMER_WAIT>200*1000000000;

    发现异常后,取到需要的信息,再

    mysql> truncate table performance_schema.file_summary_by_event_name;

    把之前的信息情况。

    MHA中,默认的方法就是select 1来检查

    优先的方案是使用update更新系统表,在配合增加检测performance_schema的信息。

  • 相关阅读:
    JavaScript数组方法--includes、indexOf、lastIndexOf
    JavaScript数组方法--flat、forEach、map
    JavaScript数组方法--filter、find、findIndex
    bootstrap-14
    bootstrap-13
    bootstrap-12
    bootstrap-11
    bootstrap-10
    bootstrap-9
    bootstrap-8
  • 原文地址:https://www.cnblogs.com/yhq1314/p/10727951.html
Copyright © 2011-2022 走看看