MySQL实战45讲
林晓斌
网名丁奇,前阿里资深技术专家
立即订阅
43178 人已学习
课程目录
已完结 48 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 这一次,让我们一起来搞懂MySQL
免费
基础篇 (8讲)
01 | 基础架构:一条SQL查询语句是如何执行的?
02 | 日志系统:一条SQL更新语句是如何执行的?
03 | 事务隔离:为什么你改了我还看不见?
04 | 深入浅出索引(上)
05 | 深入浅出索引(下)
06 | 全局锁和表锁 :给表加个字段怎么有这么多阻碍?
07 | 行锁功过:怎么减少行锁对性能的影响?
08 | 事务到底是隔离的还是不隔离的?
实践篇 (37讲)
09 | 普通索引和唯一索引,应该怎么选择?
10 | MySQL为什么有时候会选错索引?
11 | 怎么给字符串字段加索引?
12 | 为什么我的MySQL会“抖”一下?
13 | 为什么表数据删掉一半,表文件大小不变?
14 | count(*)这么慢,我该怎么办?
15 | 答疑文章(一):日志和索引相关问题
16 | “order by”是怎么工作的?
17 | 如何正确地显示随机消息?
18 | 为什么这些SQL语句逻辑相同,性能却差异巨大?
19 | 为什么我只查一行的语句,也执行这么慢?
20 | 幻读是什么,幻读有什么问题?
21 | 为什么我只改一行的语句,锁这么多?
22 | MySQL有哪些“饮鸩止渴”提高性能的方法?
23 | MySQL是怎么保证数据不丢的?
24 | MySQL是怎么保证主备一致的?
25 | MySQL是怎么保证高可用的?
26 | 备库为什么会延迟好几个小时?
27 | 主库出问题了,从库怎么办?
28 | 读写分离有哪些坑?
29 | 如何判断一个数据库是不是出问题了?
30 | 答疑文章(二):用动态的观点看加锁
31 | 误删数据后除了跑路,还能怎么办?
32 | 为什么还有kill不掉的语句?
33 | 我查这么多数据,会不会把数据库内存打爆?
34 | 到底可不可以使用join?
35 | join语句怎么优化?
36 | 为什么临时表可以重名?
37 | 什么时候会使用内部临时表?
38 | 都说InnoDB好,那还要不要使用Memory引擎?
39 | 自增主键为什么不是连续的?
40 | insert语句的锁为什么这么多?
41 | 怎么最快地复制一张表?
42 | grant之后要跟着flush privileges吗?
43 | 要不要使用分区表?
44 | 答疑文章(三):说一说这些好问题
45 | 自增id用完怎么办?
特别放送 (1讲)
直播回顾 | 林晓斌:我的 MySQL 心路历程
结束语 (1讲)
结束语 | 点线网面,一起构建MySQL知识网络
MySQL实战45讲
登录|注册

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

林晓斌 2019-01-18
我在第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),使得这三个语句都处于“执行”状态,以此来模拟大查询。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《MySQL实战45讲》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(31)

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

    作者回复: 1. 虽然理论上是核数的2倍左右最好,但是现在很多人把MySQL创建在虚拟机上,就分1~2个核,我怕那么写,有同学会认为innodb_thread_concurrency建议设置成4。。

    2. 空间满本身是不会导致连不上的。但是因为空间满,事务无法提交,可能会导致接下来外部事务重试,新重试的业务还是堵在提交阶段,持续累积可能会把连接数用满

    2019-01-20
    1
    18
  • 小菊花课堂开课啦
    老师,我有个疑问,您说外部检测是采用定时轮询的方式。那内部检测通过'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;
    '的方法,不是也需要定时轮询来执行这个语句么?

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

    而前面的几种方法,都是“检测那个时间点的信息”

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

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

    2019-01-29
    5
  • 老杨同志
    现在很多公司都是使用dubbo或者类似dubbo的rpc调用。说说我对dubbo的理解
    dubbo 存活检测感觉分为下面三个层面
    服务端与注册中心的链接状态
    通常注册中心是zookeeper,服务端注册临时节点,客户端注册这个节点的watch事件,一但服务端失联,
    客户端将把该服务从自己可用服务列表中移除。(一个服务通常有多个提供者,只是把失联的提供者移除)。
    zookeeper是通过心跳发现服务提供者失联的,心跳实际上就是以固定的频率(比如每秒)发送检测的数据包;

    客户端与注册中心的链接状态
    客户端与zookeeper失联,会暂时使用自己缓存的服务提供者列表。如果每个提供者多次调不通,把它移除。

    客户端与服务单的链接状态
        服务端提供类似于echo的方法,客户定时调用。部分返回正常,认为服务处于亚健康状态,如果超过阀值,会被降级
        从服务提供者列表移除。被移除的方法可能会在超过一定时间后,拿回来重试,可以恢复成正常服务,也可能继续降级。

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

    2019-01-18
    4
  • Mr.Strive.Z.H.L
    老师您好:
    关于 主备同步停止 的问题,看了您的回复。
    我是这么理解的:
    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
    这个冲突就会导致主备同步停止哦

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

    作者回复: 好问题

    比如两个表刚开始都是空表,
    然后第一个语句执行
    insert into mysql.health_check(id, t_modified) values (1, now()) on duplicate key update t_modified=now();

    就会两边各写入一个insert语句的binlog日志,传到对面就导致同步停止了

    2019-01-22
    2
    2
  • heat nan
    老师,一直有个疑问,想咨询下。innodb buffer 会缓存表的数据页和索引页。现在我想知道如何确认一个查询的行已经被缓存在内存中了。 我想了一下,第一种方法是直接去内存中遍历这个表相关的数据页。这样的话,因为内存中的页可能是分散的,可能不构成一个完成的索引结构,可能不能利用b+树叶子节点的路由功能。 这里有点模糊,希望老师有空可以解释一下

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

    这里不对哈

    放在内存里是b+树组织的,可以利用b+树叶子节点的路由功能的

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

    作者回复: 有DBA就不要自己去修改线上的参数啦

    如果说观察,一个比较好的管控系统,是会能够让你看到这些值的

    如果没有,就让dba给你一份线上的my.cnf的配置,然后你在测试环境自己用这个配置启动实例来观察

    2019-01-18
    2
  • lzh
    难道就没人问为啥SELECT 1不算入并发线程中吗?难道因为没查表吗?只有查了表涉及IO的才会算入并发线程?
    2019-10-02
    1
  • IT橘子
    老师,当innodb并发线程数过多导致的系统不可用问题,进行主备切换后问题就可以解决吗?备库上的innodb并发线程会不会也在一段时间之后也达到阈值呢?
    2019-07-29
    1
  • 专栏用户
    问个和本课不太相关的问题,自己开了general log,然后看到有很多set autocommit=0,之后set autocommit=1的日志,查了一下,看说是关闭/开启自动提交模式,所以就有点不懂为何会爱挨着出现这两个语句?

    作者回复: 这个是框架做的吧?

    我知道有些框架喜欢用
    set autocommit=0, 表示开启事务
    set autocommit=1,表示提交事务
    虽然也对,

    但比较建议用begin 和 commit

    2019-03-30
    1
  • alias cd=rm -rf
    1、判断进程是否可用:ping的方案(类似select 1)
    2、根据业务的需求一般会设置一个阈值以及策略(如:单位时间失败的次数,响应时间超过多少阈值)如何进行熔断、扩容等方案。
    2019-02-12
    1
  • Mr.Strive.Z.H.L
    老师您好:

    本章有个疑惑:
    ”外部检测的时候,主备使用同一条更新语句,造成行冲突,导致主备同步停止”

    上面这句话实在想不通。外部检测是只是看更新语句的返回时间,health_check表在主库备库都有,为啥会造成行冲突?为啥会导致主备同步停止?即使是相同的binlog,也没啥影响呀。

    作者回复: 比如两个表刚开始都是空表,
    然后第一个语句执行
    insert into mysql.health_check(id, t_modified) values (1, now()) on duplicate key update t_modified=now();

    就会两边各写入一个insert语句的binlog日志,传到对面就导致同步停止了

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

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

    2019-01-18
    1
  • Ryoma
    现在的服务中只加了一个healthCheck的接口,和MySQL中使用select判断比较类似。当服务依赖的MySQL及Redis等第三方资源发生问题时,还是不能有效的判断
    2019-01-18
    1
  • 长杰
    老师请教一个问题,在gtid模式下,对于大的ddl操作,采用在备库执行sql_log_bin=0的方式先执行,然后再切换主备的方式在主库再执行,这种情况下,ddl操作是不记录binlog的,不知道对gtid的计数有什么影响,是按顺序递增还是会跳过这个序列号?
    另外补充一下有些dl操作是不适合这个主备切换的方式,比如drop一个列,如果先在备库执行就可能导致主备同步异常。这个场景适合osc方式或把读请求切到主库,先在主库执行这两种方案。

    作者回复: 如果set sql_log_bin=0, 就不记录binlog,就不会给这个事务分配gtid。

    你说得对,drop列是很麻烦的,尽量不做。毕竟业务代码直接无视这个列就好了。。

    2019-01-18
    1
  • 爱因诗贤
    老师,请教一个问题,我把mysql5.5升级到mysql8.0导致大量语法报错,请问有没有什么好的解决办法
    2019-08-17
  • Shiki珠
    老师您好!请教下,我们这边每天白天几乎每个整点,业务那边有定时批量任务,那几分钟内CPU会彪到100%。活跃线程数也在200左右,QPS峰值20000+,此时也会出现平时不慢的“慢sql”,如果把innodb_thread_concurrency从0改为128或者更低,是否会有所缓解呢?但是如果限制了那有很多连接会排队等待是否会延迟,而造成业务很慢呢?
    2019-08-07
  • godtrue
    监控系统监控,达到一定条件也会触发报警,比如:慢SQL的信息,磁盘空间的信息。
    这些都是公司基础架构部做的,取得信息估计和老师讲的类似,我们主要报警信息就行。
    2019-08-04
  • null
    原文:
    如果处于锁等待状态的线程计数『不』减一,InnoDB 就会认为线程数用满了,会阻止其他语句进入引擎执行,这样线程 1 不能提交事务。

    应该是:如果处于锁等待状态的线程计数减一?
    2019-07-10
收起评论
31
返回
顶部