极客时间已完结课程限时免费阅读

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

29 | 如何判断一个数据库是不是出问题了?-极客时间

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

讲述:林晓斌

时长14:31大小13.26M

我在第2527篇文章中,和你介绍了主备切换流程。通过这些内容的讲解,你应该已经很清楚了:在一主一备的双 M 架构里,主备切换只需要把客户端流量切到备库;而在一主多从架构里,主备切换除了要把客户端流量切到备库外,还需要把从库接到新主库上。
主备切换有两种场景,一种是主动切换,一种是被动切换。而其中被动切换,往往是因为主库出问题了,由 HA 系统发起的。
这也就引出了我们今天要讨论的问题:怎么判断一个主库出问题了?
你一定会说,这很简单啊,连上 MySQL,执行个 select 1 就好了。但是 select 1 成功返回了,就表示主库没问题吗?

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)
图 1 查询 blocked
我们设置 innodb_thread_concurrency 参数的目的是,控制 InnoDB 的并发线程上限。也就是说,一旦并发线程数达到这个值,InnoDB 在接收到新请求的时候,就会进入等待状态,直到有线程退出。
这里,我把 innodb_thread_concurrency 设置成 3,表示 InnoDB 只允许 3 个线程并行执行。而在我们的例子中,前三个 session 中的 sleep(100),使得这三个语句都处于“执行”状态,以此来模拟大查询。
你看到了, session D 里面,select 1 是能执行成功的,但是查询表 t 的语句会被堵住。也就是说,如果这时候我们用 select 1 来检测实例是否正常的话,是检测不出问题的。
在 InnoDB 中,innodb_thread_concurrency 这个参数的默认值是 0,表示不限制并发线程数量。但是,不限制并发线程数肯定是不行的。因为,一个机器的 CPU 核数有限,线程全冲进来,上下文切换的成本就会太高。
所以,通常情况下,我们建议把 innodb_thread_concurrency 设置为 64~128 之间的值。这时,你一定会有疑问,并发线程上限数设置为 128 够干啥,线上的并发连接数动不动就上千了。
产生这个疑问的原因,是搞混了并发连接和并发查询。
并发连接和并发查询,并不是同一个概念。你在 show processlist 的结果里,看到的几千个连接,指的就是并发连接。而“当前正在执行”的语句,才是我们所说的并发查询。
并发连接数达到几千个影响并不大,就是多占一些内存而已。我们应该关注的是并发查询,因为并发查询太高才是 CPU 杀手。这也是为什么我们需要设置 innodb_thread_concurrency 参数的原因。
然后,你可能还会想起我们在第 7 篇文章中讲到的热点更新和死锁检测的时候,如果把 innodb_thread_concurrency 设置为 128 的话,那么出现同一行热点更新的问题时,是不是很快就把 128 消耗完了,这样整个系统是不是就挂了呢?
实际上,在线程进入锁等待以后,并发线程的计数会减一,也就是说等行锁(也包括间隙锁)的线程是不算在 128 里面的。
MySQL 这样设计是非常有意义的。因为,进入锁等待的线程已经不吃 CPU 了;更重要的是,必须这么设计,才能避免整个系统锁死。
为什么呢?假设处于锁等待的线程也占并发线程的计数,你可以设想一下这个场景:
线程 1 执行 begin; update t set c=c+1 where id=1, 启动了事务 trx1, 然后保持这个状态。这时候,线程处于空闲状态,不算在并发线程里面。
线程 2 到线程 129 都执行 update t set c=c+1 where id=1; 由于等行锁,进入等待状态。这样就有 128 个线程处于等待状态;
如果处于锁等待状态的线程计数不减一,InnoDB 就会认为线程数用满了,会阻止其他语句进入引擎执行,这样线程 1 不能提交事务。而另外的 128 个线程又处于锁等待状态,整个系统就堵住了。
下图 2 显示的就是这个状态。
图 2 系统锁死状态(假设等行锁的语句占用并发计数)
这时候 InnoDB 不能响应任何请求,整个系统被锁死。而且,由于所有线程都处于等待状态,此时占用的 CPU 却是 0,而这明显不合理。所以,我们说 InnoDB 在设计时,遇到进程进入锁等待的情况时,将并发线程的计数减 1 的设计,是合理而且是必要的。
虽然说等锁的线程不算在并发线程计数里,但如果它在真正地执行查询,就比如我们上面例子中前三个事务中的 select sleep(100) from t,还是要算进并发线程的计数的。
在这个例子中,同时在执行的语句超过了设置的 innodb_thread_concurrency 的值,这时候系统其实已经不行了,但是通过 select 1 来检测系统,会认为系统还是正常的。
因此,我们使用 select 1 的判断逻辑要修改一下。

查表判断

为了能够检测 InnoDB 并发线程数过多导致的系统不可用情况,我们需要找一个访问 InnoDB 的场景。一般的做法是,在系统库(mysql 库)里创建一个表,比如命名为 health_check,里面只放一行数据,然后定期执行:
mysql> select * from mysql.health_check;
使用这个方法,我们可以检测出由于并发线程过多导致的数据库不可用的情况。
但是,我们马上还会碰到下一个问题,即:空间满了以后,这种方法又会变得不好使。
我们知道,更新事务要写 binlog,而一旦 binlog 所在磁盘的空间占用率达到 100%,那么所有的更新语句和事务提交的 commit 语句就都会被堵住。但是,系统这时候还是可以正常读数据的。
因此,我们还是把这条监控语句再改进一下。接下来,我们就看看把查询语句改成更新语句后的效果。

更新判断

既然要更新,就要放个有意义的字段,常见做法是放一个 timestamp 字段,用来表示最后一次执行检测的时间。这条更新语句类似于:
mysql> update mysql.health_check set t_modified=now();
节点可用性的检测都应该包含主库和备库。如果用更新来检测主库的话,那么备库也要进行更新检测。
但,备库的检测也是要写 binlog 的。由于我们一般会把数据库 A 和 B 的主备关系设计为双 M 结构,所以在备库 B 上执行的检测命令,也要发回给主库 A。
但是,如果主库 A 和备库 B 都用相同的更新命令,就可能出现行冲突,也就是可能会导致主备同步停止。所以,现在看来 mysql.health_check 这个表就不能只有一行数据了。
为了让主备之间的更新不产生冲突,我们可以在 mysql.health_check 表上存入多行数据,并用 A、B 的 server_id 做主键。
mysql> 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();
由于 MySQL 规定了主库和备库的 server_id 必须不同(否则创建主备关系的时候就会报错),这样就可以保证主、备库各自的检测命令不会发生冲突。
更新判断是一个相对比较常用的方案了,不过依然存在一些问题。其中,“判定慢”一直是让 DBA 头疼的问题。
你一定会疑惑,更新语句,如果失败或者超时,就可以发起主备切换了,为什么还会有判定慢的问题呢?
其实,这里涉及到的是服务器 IO 资源分配的问题。
首先,所有的检测逻辑都需要一个超时时间 N。执行一条 update 语句,超过 N 秒后还不返回,就认为系统不可用。
你可以设想一个日志盘的 IO 利用率已经是 100% 的场景。这时候,整个系统响应非常慢,已经需要做主备切换了。
但是你要知道,IO 利用率 100% 表示系统的 IO 是在工作的,每个请求都有机会获得 IO 资源,执行自己的任务。而我们的检测使用的 update 命令,需要的资源很少,所以可能在拿到 IO 资源的时候就可以提交成功,并且在超时时间 N 秒未到达之前就返回给了检测系统。
检测系统一看,update 命令没有超时,于是就得到了“系统正常”的结论。
也就是说,这时候在业务系统上正常的 SQL 语句已经执行得很慢了,但是 DBA 上去一看,HA 系统还在正常工作,并且认为主库现在处于可用状态。
之所以会出现这个现象,根本原因是我们上面说的所有方法,都是基于外部检测的。外部检测天然有一个问题,就是随机性。
因为,外部检测都需要定时轮询,所以系统可能已经出问题了,但是却需要等到下一个检测发起执行语句的时候,我们才有可能发现问题。而且,如果你的运气不够好的话,可能第一次轮询还不能发现,这就会导致切换慢的问题。
所以,接下来我要再和你介绍一种在 MySQL 内部发现数据库问题的方法。

内部统计

针对磁盘利用率这个问题,如果 MySQL 可以告诉我们,内部每一次 IO 请求的时间,那我们判断数据库是否出问题的方法就可靠得多了。
其实,MySQL 5.6 版本以后提供的 performance_schema 库,就在 file_summary_by_event_name 表里统计了每次 IO 请求的时间。
file_summary_by_event_name 表里有很多行数据,我们先来看看 event_name='wait/io/file/innodb/innodb_log_file’这一行。
图 3 performance_schema.file_summary_by_event_name 的一行
图中这一行表示统计的是 redo log 的写入时间,第一列 EVENT_NAME 表示统计的类型。
接下来的三组数据,显示的是 redo log 操作的时间统计。
第一组五列,是所有 IO 类型的统计。其中,COUNT_STAR 是所有 IO 的总次数,接下来四列是具体的统计项, 单位是皮秒;前缀 SUM、MIN、AVG、MAX,顾名思义指的就是总和、最小值、平均值和最大值。
第二组六列,是读操作的统计。最后一列 SUM_NUMBER_OF_BYTES_READ 统计的是,总共从 redo log 里读了多少个字节。
第三组六列,统计的是写操作。
最后的第四组数据,是对其他类型数据的统计。在 redo log 里,你可以认为它们就是对 fsync 的统计。
在 performance_schema 库的 file_summary_by_event_name 表里,binlog 对应的是 event_name = "wait/io/file/sql/binlog"这一行。各个字段的统计逻辑,与 redo log 的各个字段完全相同。这里,我就不再赘述了。
因为我们每一次操作数据库,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 log 和 binlog 这两个统计信息,那要怎么把这个信息用在实例状态诊断上呢?
很简单,你可以通过 MAX_TIMER 的值来判断数据库是否出问题了。比如,你可以设定阈值,单次 IO 请求时间超过 200 毫秒属于异常,然后使用类似下面这条语句作为检测逻辑。
mysql> 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;
把之前的统计信息清空。这样如果后面的监控中,再次出现这个异常,就可以加入监控累积值了。

小结

今天,我和你介绍了检测一个 MySQL 实例健康状态的几种方法,以及各种方法存在的问题和演进的逻辑。
你看完后可能会觉得,select 1 这样的方法是不是已经被淘汰了呢,但实际上使用非常广泛的 MHA(Master High Availability),默认使用的就是这个方法。
MHA 中的另一个可选方法是只做连接,就是 “如果连接成功就认为主库没问题”。不过据我所知,选择这个方法的很少。
其实,每个改进的方案,都会增加额外损耗,并不能用“对错”做直接判断,需要你根据业务实际情况去做权衡。
我个人比较倾向的方案,是优先考虑 update 系统表,然后再配合增加检测 performance_schema 的信息。
最后,又到了我们的思考题时间。
今天,我想问你的是:业务系统一般也有高可用的需求,在你开发和维护过的服务中,你是怎么判断服务有没有出问题的呢?
你可以把你用到的方法和分析写在留言区,我会在下一篇文章中选取有趣的方案一起来分享和分析。感谢你的收听,也欢迎你把这篇文章分享给更多的朋友一起阅读。

上期问题时间

上期的问题是,如果使用 GTID 等位点的方案做读写分离,在对大表做 DDL 的时候会怎么样。
假设,这条语句在主库上要执行 10 分钟,提交后传到备库就要 10 分钟(典型的大事务)。那么,在主库 DDL 之后再提交的事务的 GTID,去备库查的时候,就会等 10 分钟才出现。
这样,这个读写分离机制在这 10 分钟之内都会超时,然后走主库。
这种预期内的操作,应该在业务低峰期的时候,确保主库能够支持所有业务查询,然后把读请求都切到主库,再在主库上做 DDL。等备库延迟追上以后,再把读请求切回备库。
通过这个思考题,我主要想让关注的是,大事务对等位点方案的影响。
当然了,使用 gh-ost 方案来解决这个问题也是不错的选择。
评论区留言点赞板:
@曾剑、@max 同学提到的备库先做,再切主库的方法也是可以的。
分享给需要的人,Ta购买本课程,你将得20
生成海报并分享

赞 46

提建议

上一篇
28 | 读写分离有哪些坑?
下一篇
30 | 答疑文章(二):用动态的观点看加锁
unpreview
 写留言

精选留言(56)

  • 某、人
    2019-01-20
    目前是只有一台服务器来做判断,是否数据库出问题了,就是采用的update的方式。如果是主从架构就一条语句,如果是双主的话就是两条update语句。但是这种方式有很大的弊端,只有一个进程来判断数据库出问题的话,会出现单点判断的问题。所以后续准备多个单数进程来做判断,如果超过了半数以上的监控进程都认为数据库出问题,才做切换。 老师我有两个问题: 1.innodb_thread_concurrency的设置是不是应该跟计算机核数成正比,一般是1.5倍-2倍左右? 2.怎么之前遇到空间满了,数据库都登不上了,所有的连接都连不上,更不用执行select语句了,这个是什么原因啊?
    展开

    作者回复: 1. 虽然理论上是核数的2倍左右最好,但是现在很多人把MySQL创建在虚拟机上,就分1~2个核,我怕那么写,有同学会认为innodb_thread_concurrency建议设置成4。。 2. 空间满本身是不会导致连不上的。但是因为空间满,事务无法提交,可能会导致接下来外部事务重试,新重试的业务还是堵在提交阶段,持续累积可能会把连接数用满

    共 4 条评论
    73
  • StarkYanng
    2019-02-16
    老师,我有个疑问,您说外部检测是采用定时轮询的方式。那内部检测通过'mysql> 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; '的方法,不是也需要定时轮询来执行这个语句么?

    作者回复: 对,但是这个方法本质上是“内部把一段时间内的统计信息存在这里”,只是“定期来取”,去到的是“一段时间内的信息” 而前面的几种方法,都是“检测那个时间点的信息”

    共 2 条评论
    51
  • 老杨同志
    2019-01-18
    现在很多公司都是使用dubbo或者类似dubbo的rpc调用。说说我对dubbo的理解 dubbo 存活检测感觉分为下面三个层面 服务端与注册中心的链接状态 通常注册中心是zookeeper,服务端注册临时节点,客户端注册这个节点的watch事件,一但服务端失联, 客户端将把该服务从自己可用服务列表中移除。(一个服务通常有多个提供者,只是把失联的提供者移除)。 zookeeper是通过心跳发现服务提供者失联的,心跳实际上就是以固定的频率(比如每秒)发送检测的数据包; 客户端与注册中心的链接状态 客户端与zookeeper失联,会暂时使用自己缓存的服务提供者列表。如果每个提供者多次调不通,把它移除。 客户端与服务单的链接状态 服务端提供类似于echo的方法,客户定时调用。部分返回正常,认为服务处于亚健康状态,如果超过阀值,会被降级 从服务提供者列表移除。被移除的方法可能会在超过一定时间后,拿回来重试,可以恢复成正常服务,也可能继续降级。
    展开

    作者回复: 很好的实践分享。 是不是还有配套一些服务的RT时间的报告? 毕竟echo是一个比较轻量的调用,正确率可能比实际业务调用的正确率高

    共 5 条评论
    28
  • IceGeek17
    2019-01-29
    对于使用 GTID 等位点的方案做读写分离,对大表做DDL的问题, 有一种做法是先在从库上设置 set_log_bin = off,在从库上先做DDL,完成后做一下主从切换。然后再在之前的主库上同样操作一遍。 但这会有一个问题,当先在从库上做DDL(大表DDL时间会比较长,比如10分钟),在这段时间内,此时如果读写请求都走主库的话,如果写请求对于DDL的改动是有依赖的,那这些写请求在主库就可能会失败;同样此时对于主库上的读请求,也可能会读到“过期”的数据(读请求希望读到DDL之后的数据,但此时DDL在从库执行,主库上还是DDL之前的),老师怎么看这个问题 ?
    展开

    作者回复: 是这样的,我们说DDL,一般是指加减索引,增加字段在最后一列,这种操作…

    共 8 条评论
    14
  • 强哥
    2019-01-18
    1.基础监控,包括硬盘,CPU,网络,内存等。 2.服务监控,包括jvm,服务端口,接入上下游服务的超时监控等。 3.业务监控,主要是监控业务的流程是否出现问题。

    作者回复: 👍,这里的“超时监控”,是怎么得到的? 是单独有命令检测,还是去看业务请求的返回时间?

    共 2 条评论
    13
  • 专栏用户
    2019-03-30
    问个和本课不太相关的问题,自己开了general log,然后看到有很多set autocommit=0,之后set autocommit=1的日志,查了一下,看说是关闭/开启自动提交模式,所以就有点不懂为何会爱挨着出现这两个语句?

    作者回复: 这个是框架做的吧? 我知道有些框架喜欢用 set autocommit=0, 表示开启事务 set autocommit=1,表示提交事务 虽然也对, 但比较建议用begin 和 commit

    11
  • 长杰
    2019-01-18
    老师请教一个问题,在gtid模式下,对于大的ddl操作,采用在备库执行sql_log_bin=0的方式先执行,然后再切换主备的方式在主库再执行,这种情况下,ddl操作是不记录binlog的,不知道对gtid的计数有什么影响,是按顺序递增还是会跳过这个序列号? 另外补充一下有些dl操作是不适合这个主备切换的方式,比如drop一个列,如果先在备库执行就可能导致主备同步异常。这个场景适合osc方式或把读请求切到主库,先在主库执行这两种方案。
    展开

    作者回复: 如果set sql_log_bin=0, 就不记录binlog,就不会给这个事务分配gtid。 你说得对,drop列是很麻烦的,尽量不做。毕竟业务代码直接无视这个列就好了。。

    共 2 条评论
    11
  • Mr.Strive.Z.H.L
    2019-01-22
    老师您好: 关于 主备同步停止 的问题,看了您的回复。 我是这么理解的: insert into mysql.health_check(id, t_modified) values (1, now()) on duplicate key update t_modified=now(); 按照您说的场景,主备分别执行这句话后,复制给彼此。 如果单单看这句话,就算是主库执行备库复制过来的这句话,也不会出现异常呀。(因为如果主键冲突就会更新时间) 但是这种场景会导致 主备同步停止, 所以实际上主库在应用备库这句话的binlog的时候,发现主键冲突,自然就会报错。 不知道是不是这样,因为如果单单看这句sql,即使主键冲突也没关系呀?
    展开

    作者回复: 啊 主键冲突为啥没关系? 是这样的,这两个语句如果同时执行,那么在主库和备库上就都是“insert行为” 写到binlog里面就都是Write rows event 这个冲突就会导致主备同步停止哦

    共 6 条评论
    9
  • 慧鑫coming
    2019-01-22
    老师,文中提到的“但是,如果主库 A 和备库 B 都用相同的更新命令,就可能出现行冲突,也就是可能会导致主备同步停止。”,这个能展开说一下吗,这个行冲突指什么?它们会都更新各自检测表的同一字段我觉得会带来不准确的问题,怎么导致主从同步停止了呢?

    作者回复: 好问题 比如两个表刚开始都是空表, 然后第一个语句执行 insert into mysql.health_check(id, t_modified) values (1, now()) on duplicate key update t_modified=now(); 就会两边各写入一个insert语句的binlog日志,传到对面就导致同步停止了

    共 10 条评论
    9
  • 路平
    2019-04-23
    你好,这两天一路看下来,收获不少。 提个表设计相关的问题: 用一个表存储文件全路径,删除某个文件(一行记录)时使用逻辑删除。怎么设计表及其索引(如果有)? 需要考虑: 1. 文件被删除后有可能会再创建一个同名的文件; 2. 新创建的文件也可能再次被逻辑删除; 3. 第二个文件被删除后还可能创建第三同名文件,以此类推; 4. 未删除的文件路径不能有重复值。 不知道作者是否还会回复留言。如果回复了,我是会收到提醒吗?
    展开

    作者回复: 如果你是要保存“历史”,可以加两个字段:版本号和状态(表示是否删除) 【编辑跟我说会有提醒~】

    共 3 条评论
    8
  • 一大只😴
    2019-01-21
    老师,我想问下,我的ECS上是8核CPU,只跑一个MySQL实例,那innodb_thread_concurrency如果设成2倍,那就是16哈。看并发查询的数量,是不是关注Threads_running是否超过innodb_thread_concurrency就可以了。

    作者回复: Thread running 是包含“锁等待”状态的线程的, 超过点也没事😄

    共 2 条评论
    6
  • Mr.Strive.Z.H.L
    2019-01-22
    老师您好: 本章有个疑惑: ”外部检测的时候,主备使用同一条更新语句,造成行冲突,导致主备同步停止” 上面这句话实在想不通。外部检测是只是看更新语句的返回时间,health_check表在主库备库都有,为啥会造成行冲突?为啥会导致主备同步停止?即使是相同的binlog,也没啥影响呀。
    展开

    作者回复: 比如两个表刚开始都是空表, 然后第一个语句执行 insert into mysql.health_check(id, t_modified) values (1, now()) on duplicate key update t_modified=now(); 就会两边各写入一个insert语句的binlog日志,传到对面就导致同步停止了

    5
  • lzh
    2019-10-02
    难道就没人问为啥SELECT 1不算入并发线程中吗?难道因为没查表吗?只有查了表涉及IO的才会算入并发线程?
    共 6 条评论
    3
  • heat nan
    2019-01-19
    老师,一直有个疑问,想咨询下。innodb buffer 会缓存表的数据页和索引页。现在我想知道如何确认一个查询的行已经被缓存在内存中了。 我想了一下,第一种方法是直接去内存中遍历这个表相关的数据页。这样的话,因为内存中的页可能是分散的,可能不构成一个完成的索引结构,可能不能利用b+树叶子节点的路由功能。 这里有点模糊,希望老师有空可以解释一下

    作者回复: “因为内存中的页可能是分散的,可能不构成一个完成的索引结构,可能不能利用b+树叶子节点的路由功能。” 这里不对哈 放在内存里是b+树组织的,可以利用b+树叶子节点的路由功能的

    3
  • 布衣骇客
    2019-01-18
    作为一个开发我也很想了解一下我们自己生产库上的监控情况,接触到最多的就是Datasource,以及user,password,port(基本上是基于连接那种级别,最多就是加锁),等等参数,大部分都是基于业务开发。站在个人层面或者业务开发层面(很少能接触到DBA,以及看到DBA是怎么设置这些参数情况,除非库挂掉了就会和DBA一起看这些)怎么去修改和观看以及使用这些参数鸭

    作者回复: 有DBA就不要自己去修改线上的参数啦 如果说观察,一个比较好的管控系统,是会能够让你看到这些值的 如果没有,就让dba给你一份线上的my.cnf的配置,然后你在测试环境自己用这个配置启动实例来观察

    3
  • Ryoma
    2019-01-18
    现在的服务中只加了一个healthCheck的接口,和MySQL中使用select判断比较类似。当服务依赖的MySQL及Redis等第三方资源发生问题时,还是不能有效的判断
    2
  • Shiki珠
    2019-08-07
    老师您好!请教下,我们这边每天白天几乎每个整点,业务那边有定时批量任务,那几分钟内CPU会彪到100%。活跃线程数也在200左右,QPS峰值20000+,此时也会出现平时不慢的“慢sql”,如果把innodb_thread_concurrency从0改为128或者更低,是否会有所缓解呢?但是如果限制了那有很多连接会排队等待是否会延迟,而造成业务很慢呢?
    共 3 条评论
    1
  • IT橘子
    2019-07-29
    老师,当innodb并发线程数过多导致的系统不可用问题,进行主备切换后问题就可以解决吗?备库上的innodb并发线程会不会也在一段时间之后也达到阈值呢?
    1
  • alias cd=rm -rf
    2019-02-12
    1、判断进程是否可用:ping的方案(类似select 1) 2、根据业务的需求一般会设置一个阈值以及策略(如:单位时间失败的次数,响应时间超过多少阈值)如何进行熔断、扩容等方案。
    1
  • 黄文晓
    2023-01-17 来自广东
    判断数据库是否可用的方法: 1、select 1 :只能判断数据库进程,没有触及到引擎层,不能发现并发线程数过多导致的数据库不可用问题(ps:线程进入锁等待,并发线程数计数减一) 2、查表:可以发现并发线程数过多导致的数据库不可用问题,但是不能发现由于binlog所在磁盘满了导致所有事务不能提交导致数据库不可用问题 3、更新表:可以发现由于binlog所在磁盘满了导致所有事务不能提交导致数据库不可用问题,但是具有随机性 4、内部统计:performance_schema库的file_summary_by_event_name表MAX_TIMER_WAIT
    展开
新人学习立返 50% 购课币
去订阅《MySQL实战45讲》新人首单¥68