mysql常见问题总结
前段时间都在准备面试,对mysql常见的问题进行总结,希望可以帮助需要的人
MySQL版本类问题
用户管理类问题
服务器配置类问题
日志类问题
存储引擎相关问题
MySQL架构类问题
备份恢复类问题
管理及监控类问题
优化及异常处理
MySQL版本类问题
你之前工作中使用的是什么版本的MySQL?为什么要选择这个版本?
在工作中我所使用的mysql版本为5.7,使用该版本的原因是该版本功能齐全,是有经历过大规模使用的稳定版本,基本上不会触发致命bug。对于版本的选取主要的依据包括版本是否稳定,是否兼容项目功能,是否为官方发布的稳定版本,该版本前后几个月是否有大的bug修复版本等。
如何决定是否要对MySQL进行升级?如何进行升级?
在升级mysql版本之前,首先要查看最新要升级的版本的更新变化,了解清楚是否符合我们的升级需求,包括是否稳定,是否有功能满足我们的需求,效率是否有所提升等或是当前版本不稳定,存在bug。
关于如何升级:
1.导出所有用户的权限
2.导出所有数据并恢复到新版本数据库中
3.恢复用户权限到新数据库中
最新版本MySQL版本是什么?它有什么特性比较吸引你?
Mysql最新版本为8.0
新特性包括:
一、账户与安全
1.用户的创建与授权
在MySQL5.7的版本:
grant all privileges on . to ‘用户名‘@’主机’ identified by ‘密码’;
在MySQL8.0需要分开执行:
create user ‘用户名‘@’主机’ identified by ‘密码’;
grant all privileges on . to ‘用户名‘@’主机’;
用以前的一条命令在8.0里面创建用户,会出现sql语法错误
2.认证插件更新
MySQL5.7默认身份插件是mysql_native_password
MySQL8.0默认的身份插件是caching_sha2_password
3.密码管理
MySQL8.0的密码管理策略有3个变量
- password_history 修改密码不允许与最近几次使用或的密码重复,默认是0,即不限制
- password_reuse_interval 修改密码不允许与最近多少天的使用过的密码重复,默认是0,即不限制
- password_require_current 修改密码是否需要提供当前的登录密码,默认是OFF,即不需要;如果需要,则设置成ON
4.角色管理
角色:一组权限的集合
一组权限赋予某个角色,再把某个角色赋予某个用户,那用户就拥有角色对应的权限
二、优化器索引
1.隐藏索引(invisible index)
应用场景:
1)软删除
删除索引,在线上,如果删除错了索引,只能通过创建索引的方式将其添加回来,对于一些大的数据库而言,是比较耗性能的;为了避免删错,可以先将其设置为不可见,优化器这时候就不会使用它,但是后台仍然在维护,确定后,再删除。
2)灰度发布
与软删除差不多,如果想要测试一些索引的功能或者随后可能会使用到这个索引,可以先将其设置为隐藏索引,对于现有的查询不会产生影响,测试后,确定需要该索引,可以将其设置成可见索引。
2.降序索引(descending index)
MySQL8.0开始真正支持降序索引,只有InnoDB引擎支持降序所以,且必须是BTREE降序索引,MySQL8.0不在对group by操作进行隐式排序。
3.函数索引
索引中使用函数表达式,支持JSON数据节点的索引,函数索引是基于虚拟列的功能实现的
三、通用表表达式
四、窗口函数
五、InnoDB增强
- 集成数据字段
- 原子ddl操作
- 自增列持久化
- 死锁检查控制
- 锁定语句选项
六、JSON增强
- 内联路径操作符
- JSON聚合函数
- JSON实用函数
- JSON合并函数
- JSON表函数
用户管理类问题
如何在给定场景下为某用户授权?
根据最新的mysql8.0版本的操作来,在8.0之前的版本用户的创建和授权可以写在一个语句中,而8.0后,用户的创建和授权必须语句必须分开写。
首先我们必须创建用户,通过语句 CREATE USER '用户名'@'访问host' IDENTIFIED BY '用户密码'
;
再使用grant命令对用户授权 grant 权限列表 on 数据库.数据表 to 用户名@访问主机
;
当然我们还可以通过revoke命令撤销用户权限 revoke 权限列表 on 数据库名.表名 from 用户名@访问主机
当我们为用户分配权限后,还需要执行flush privileges
刷新权限让其立刻生效
为新用户分配权限时,应遵循最小权限原则,使用grant命令对用户授权,使用revoke撤销权限
常用的权限包括:
Admin权限:
- Create User 建立新的用户的权限
- Grant option 为其他用户授权的权限
- Super 管理服务器的权限
DDL权限
- Create 新建数据库,表的权限
- Alter 修改表结构的权限
- Drop 删除数据库和表的权限
- Index 建立和删除索引的权限
DML权限
- Select 查询表中数据的权限
- Insert 向表中插入数据的权限
- Update 更新表中数据的权限
- Delete 删除表中数据的权限
- Execute 执行存储过程的权限
如何保证数据库账号的安全?
- 最小权限原则
- 密码强度策略
- 密码过期原则
- 限制历史密码重用原则
服务器配置类问题
请分析一个Group By语句的异常原因
可能原因是sql_mode参数设置问题,sql_mode是个很容易被忽视的变量,它定义了你MySQL应该支持的sql语法,对数据的校验等等,默认值是空值,在这种设置下是可以允许一些非法操作的,比如允许一些非法数据的插入。在生产环境必须将这个值设置为严格模式,所以开发、测试环境的数据库也必须要设置,这样在开发测试阶段就可以发现问题.
sql_model 常用来解决下面几类问题
(1) 通过设置sql_mode, 可以完成不同严格程度的数据校验,有效地保障数据准备性。
(2) 通过设置sql_model为宽松模式,来保证大多数sql符合标准的sql语法,这样应用在不同数据库之间进行迁移时,则不需要对业务sql 进行较大的修改。
(3) 在不同数据库之间进行数据迁移之前,通过设置sql_mode可以使MySQL上的数据更方便地迁移到目标数据库中。
sql_mode常用值如下:
- ONLY_FULL_GROUP_BY:对于GROUP BY聚合操作,如果在SELECT中的列,没有在GROUP BY中出现,那么这个SQL是不合法的,因为列不在GROUP BY从句中
- NO_AUTO_VALUE_ON_ZERO:该值影响自增长列的插入。默认设置下,插入0或NULL代表生成下一个自增长值。如果用户 希望插入的值为0,而该列又是自增长的,那么这个选项就有用了。
- STRICT_TRANS_TABLES:在该模式下,如果一个值不能插入到一个事务表中,则中断当前的操作,对非事务表不做限制
- NO_ZERO_IN_DATE:在严格模式下,不允许日期和月份为零
- NO_ZERO_DATE:设置该值,mysql数据库不允许插入零日期,插入零日期会抛出错误而不是警告。
- ERROR_FOR_DIVISION_BY_ZERO:在INSERT或UPDATE过程中,如果数据被零除,则产生错误而非警告。如果未给出该模式,那么数据被零除时MySQL返回NULL
- NO_AUTO_CREATE_USER:禁止GRANT创建密码为空的用户
- NO_ENGINE_SUBSTITUTION:如果需要的存储引擎被禁用或未编译,那么抛出错误。不设置此值时,用默认的存储引擎替代,并抛出一个异常
- PIPES_AS_CONCAT: 将”||”视为字符串的连接操作符而非或运算符,这和Oracle数据库是一样的,也和字符串的拼接函数Concat相类似
- ANSI_QUOTES:启用ANSI_QUOTES后,不能用双引号来引用字符串,因为它被解释为识别符
如何比较系统运行配置和配置文件中的配置是否一致?
在数据库运行时,我们会通过set命令动态地修改数据库配置,这时系统运行配置和配置文件的配置就会存在不一致的情况。
使用set命令配置动态参数,可分为三种方式动态地修改数据库配置,session为只作用于当前进程;global为只作用于当前运行数据库,若数据库重启则失效;persist为8.0版本推出的永久修改配置
set [session | @@session.] system_var_name = expr
set [global | @@global .] system_var_name = expr
set [persist| @@persist.] system_var_name = expr
比较系统运行配置和配置文件配置可以使用pt-config-diff工具比较配置文件
pt-config-diff u=root,p=xxxx,h=localhost /etc/my.cnf
举几个MYSQL中关键性能参数
1、服务器配置参数
参数 | 说明 |
---|---|
max_connections | 设置 MySQL 允许访问的最大连接数 |
interactive_timeout | 设置交互连接的 timeout 时间 |
wait_timeout | 设置非交互连接的 timeout 时间 |
max_allowed_packet | 控制 MySQL 可以接收的数据包大小 |
sync_binlog | 表示每写多少次缓冲会向磁盘同步一次 binlog |
sort_buffer_size | 设置每个会话使用的排序缓存区的大小 |
join_buffer_size | 设置每个会话所使用的连接缓冲的大小 |
read_buffer_size | 指定了当对一个 MYISAM 进行扫描时所分配的读缓存池的大小 |
read_rnd_buffer_size | 设置控制索引缓冲区的大小 |
binllog_cache_size | 设置每个会话用于缓存未提交的事务缓存大小 |
2、储存引擎参数
参数 | 说明 |
---|---|
innodb_flush_log_at_trx_commit | 0:每秒进行一次重做日志的磁盘刷新操作 1:每次事务提交d都会刷新事务日志到磁盘中 2:每次事务提交写入系统缓存每秒向磁盘刷新一次 |
innodb_buffer_pool_size | 设置 innodb 缓冲池的大小,应为系统可用内存的 75% |
innodb_buffer_pool_instances | innodb缓冲池的实例个数,每个实例的大小为总缓冲池大小/实例个数 |
innodb_file_per_table | 设置每个表独立使用一个表空间文件 |
日志类问题
常用的MySQL日志有哪些?我们在什么情况下使用这些日志?
- 错误日志(error_log):记录mysql在启动、运行或停止时出现的问题,可用于分析排除MySQL运行错误,记录未经授权的访问
- 常规日志(general_log):记录所有发向mysql的请求,可用于分析客户端发送到MySQL的实际请求
- 慢查询日志(slow_query_log):记录所有执行时间超过long_query_time的所有查询或不使用索引的查询。可用于将执行成功并符合条件的查询记录到日志中,找到需要优化的SQL
- 二进制日志(binary_log):记录全部有效的额数据修改日志,可用于记录所有对数据库中数据的修改,基于时间点的备份和恢复,主从复制
- 中继日志(relay_log):用于主从复制,临时存储从主库同步的二进制日志
错误日志(error_log):
在MySQL配置文件中,错误日志所记录的信息可以通过log-error和log-warnings来定义,其中log-err定义是否启用错误日志功能和错误日志的存储位置log-warnings定义是否将警告信息也记录到错误日志中。
常规日志(general_log):
常规日志会记录mysqld所有相关操作,当clients连接或断开连接时,服务器将信息写入此日志,并记录从clients收到的每个 SQL语句。当你怀疑client中的错误并想要确切知道client发送给mysqld的内容时,通用查询日志非常有用。默认情况下,general log是关闭的,开启通用查询日志会增加很多磁盘I/O, 所以如非出于调试排错目的,不建议开启通用查询日志。
相关参数配置介绍如下:
general_log = 0 #默认值是0,即不开启,可设置为1
general_log_file = /data/mysql/logs/general.log #指定日志位置及名称
sql_log_off=off #在session级别控制是否启用一般查询日志,默认为off,即启用
慢查询日志(slow_query_log):
查询超出变量long_query_time指定时间值的为慢查询。但是查询获取锁(包括锁等待)的时间不计入查询时间内。
mysql记录慢查询日志是在查询执行完毕且已经完全释放锁之后才记录的,因此慢查询日志记录的顺序和执行的SQL查询语句顺序可能会不一致(例如语句1先执行,查询速度慢,语句2后执行,但查询速度快,则语句2先记录)。
相关参数配置介绍如下:
long_query_time=10 # 指定慢查询超时时长(默认10秒),超出此时长的属于慢查询
log_output={TABLE|FILE|NONE} # 定义一般查询日志和慢查询日志的输出格式,默认为file
log_slow_queries={yes|no} # 是否启用慢查询日志,默认不启用
slow_query_log={1|ON|0|OFF} # 也是是否启用慢查询日志,此变量和log_slow_queries修改一个另一个同时变化
slow_query_log_file=/mydata/data/hostname-slow.log #默认路径为库文件目录下主机名加上-slow.log
log_queries_not_using_indexes=OFF # 查询没有使用索引的时候是否也记入慢查询日志
二进制日志(binary_log):
二进制日志包含了引起或可能引起数据库改变(如delete语句但没有匹配行)的事件信息,但绝不会包括select和show这样的查询语句。
语句以”事件”的形式保存,所以包含了时间、事件开始和结束位置等信息。
二进制日志是以事件形式记录的,不是事务日志(但可能是基于事务来记录二进制日志),不代表它只记录innodb日志,myisam表也一样有二进制日志。
对于事务表的操作,二进制日志只在事务提交的时候一次性写入(基于事务的innodb二进制日志),提交前的每个二进制日志记录都先cache,提交时写入。所以,对于事务表来说,一个事务中可能包含多条二进制日志事件,它们会在提交时一次性写入。
而对于非事务表的操作,每次执行完语句就直接写入。
相关参数配置介绍如下:
log_bin #指定binlog是否开启及文件名称。
server_id #指定服务器唯一ID,开启binlog 必须设置此参数。
binlog_format #指定binlog模式,建议设置为ROW。
max_binlog_size #控制单个二进制日志大小,当前日志文件大小超过此变量时,执行切换动作。
expire_logs_days #控制二进制日志文件保留天数,默认值为0,表示不自动删除,可设置为0~99。
中继日志(relay_log):
中继日志用于主从复制架构中的从服务器上,从服务器的slave进程从主服务器处获取二进制日志的内容并写入中继日志,然后由 IO 进程读取并执行中继日志中的语句。
相关参数配置介绍如下:
relay_log #定义relay log的位置和名称。
relay_log_purge #是否自动清空不再需要中继日志,默认值为1(启用)。
relay_log_recovery #当slave从库宕机后,假如relay log损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的relay log ,并且重新从master上获取日志,这样就保证了relay log的完整性。默认情况下该功能是关闭的,将 relay_log_recovery 的值设置为1可开启此功能。
如何通过日志来审计用户活动
可以开启常规日志和错误日志,用于分析记录用户的访问情况,执行了什么行为等等
存储引擎相关问题
说一说你了解的mysql存储引擎及其适用场景
引擎名称 | 是否支持事务 | 说明 |
---|---|---|
MYISAM | 否 | mysql5.6之前默认存储引擎,最常用的非事务型存储引擎 |
CSV | 否 | 以CSV格式存储的非事务型存储引擎 |
Archive | 否 | 只运行查询和新增数据而不允许修改的非事务型存储引擎 |
Memory | 否 | 是一种易失性非事务型存储引擎 |
INNODB | 是 | 最常用的事务型存储引擎 |
NDB | 是 | mysql集群所使用的内存型事务存储引擎 |
MYISAM引擎的特点:
- 非事务型存储引擎
- 以堆表方式存储
- 使用表级锁
- 支持Btree索引,空间索引,全文索引
适用场景:
- 读操作远远大于写操作的场景
- 不需要使用事务的场景
CSV引擎的特点:
- 非事务型存储引擎
- 数据以CSV格式存储
- 所有列都不能为NULL
- 不支持索引
适用场景:
- 做为数据交换的中间表使用
Archive引擎的特点:
- 非事务型存储引擎
- 表数据使用zlib压缩
- 只支持Insert和Select
- 只允许在自增ID上建立索引
适用场景:
- 日志和数据采集类应用
- 数据归档存储
Memory引擎的特点:
- 非事务型存储引擎
- 数据保存在内存中
- 所有字段长度固定
- 支持Btree和Hash索引
适用场景:
- 用于缓存字段映射表
- 缓存周期性分析数据
Innodb引擎的特点:
- 事务型存储引擎支持ACID
- 数据按主键聚集存储
- 支持行级锁及MVCC
- 支持Btree和自适应Hash索引
- 支持全文和空间索引
适用场景:
- 适用于绝大多数场景
NDB引擎的特点:
- 事务型存储引擎
- 数据存储在内存中
- 支持行级锁
- 支持高可用集群
- 支持Ttree索引
在什么情况下Innodb无法在线修改表结构
操作 | 语法 |
---|---|
加全文索引 | CREATE FULLTEXT INDEX name ON table(column) |
加空间索引 | ALTER TABLE geom ADD SPATlAL INDEX(g) |
删除主键 | ALTER TABLE tbl_name DROP PRIMARY KEY |
增加自增列 | alter table t add column id int auto_increment not null primary key |
修改列类型 | ALTER TABLE tbl_name CHANGE c1 c1 NEW_TYPE |
修改字符集 | ALTER TABLE tbl_name CHARACTER SET = charset_name |
在线DDL存在的问题:
- 有部分语句不支持在线DDL
- 长时间的DDL操作会引起严重的主从延迟
- 无法对DDL操作进行资源限制
在无法进行在线修改表结构的情况下,要如何操作?
Innodb是如何实现事务的?
什么是事务?通俗来说就是一组SQL语句,而且这组SQL要么同时都执行成功要么同时都不成功。
事务的特性:
特征 | 说明 |
---|---|
原子性(A) | 一个事务中的所有操作,要么全都成功,要么全都不成功,不会结束在中间某个环节; |
一致性(C) | 事务开始之前和结束之后,数据库的完整性没有被破坏; |
隔离性(I) | 要求每个读写事务的操作对象与其他事务的操作对象能相互隔离; |
持久性(D) | 事务一旦提交,其结果就会持久化,就算发生宕机也能恢复数据; |
利用回滚日志(undo log) 和 重做日志(redo log) 两种表实现事务,并实现 MVCC (多版本并发控制);
在执行事务的每条SQL时,会先将数据原值写入undo log 中, 然后执行SQL对数据进行修改,最后将修改后的值写入redo log中。
redo log 重做日志包括两部分:1 是内存中的重做日志缓冲 ;2 是重做日志文件。在事务提交时,必须先将该事务的所有日志写入到重做日志文件进行持久化,待事务commit操作完成才算完成。
当一个事务中的所有SQL都执行成功后,会将redo log 缓存中的数据刷入磁盘,然后提交。
如果发生回滚,会根据undo log 恢复数据。
特征 | INNODB实现方式 |
---|---|
原子性(A) | 回滚日志(undo log):用于记录数据修改前的状态; |
一致性(C) | 重做日志(redo log):用于记录数据修改后的状态; |
隔离性(I) | 锁:用于资源隔离,分为共享锁和排它锁; |
持久性(D) | 重做日志(redo log) + 回滚日志(undo log); |
MVCC 多版本并发控制
查询需要对资源加共享锁(S),数据修改需要对资源加排他锁(X)
排他锁 | 共享锁 | |
---|---|---|
排他锁 | 不兼容 | 不兼容 |
共享锁 | 不兼容 | 兼容 |
利用undo log使读写不阻塞,实现了可重复读。当一个事务正在对一条数据进行修改时,该资源会被加上排它锁。在事务未提交时对加锁资源进行读操作时,读操作无法读到被锁资源,通过一些特殊的标志符去读undo log 中的数据(过程很复杂),这样读到的都是事务执行之前的数据。
Innodb读操作是否会阻塞写操作?
如果我们在读操作添加记录锁,间隙锁,临键锁等操作是会阻塞写操作的,如使用select * from t where id = 1 for update
语句
MySQL架构类问题
mysql的主从复制是如何工作的
MySQL的主从复制是一个异步的复制过程,数据库从一个Master复制到Slave数据库,在Master与Slave之间实现整个主从复制的过程是由三个线程参与完成的,其中有两个线程(SQL线程和IO线程)在Slave端,另一个线程(IO线程)在Master端。
MySQL主从复制之前我们需要先启动Master数据库然后再启动Salve数据库,然后在Salve数据库中执行start slave;,执行完成之后,流程就如下了:
Salve的IO线程会读取mastr.info文件中配置好的主库信息,比如说存放的有:Master数据库的用户名、密码、端口、还有Master的binlog索引位置;
拿到信息之后就带着信息去链接Master的主库IO线程
当主库的IO线程先检查SLave传过来的配置信息是否正确,如果正确,就拿着Slave传过来的binlog索引位置和Master库的binlog文件中最后一个索引位置进行对比,如果一致就陷入等待状态,等待Master的binlog索引位置更新;
如果不一致就把Slave传过来的binlog索引位置往后的所有SQL语句包括最后一条SQL语句的索引位置发送个给Slave的IO线程;
Slave的IO线程拿到信息之后,先把Master传过来的binlog索引在Slave的master.info文件中进行更新;
然后再把Master传过来的SQL语句写入到relay文件中,然后继续循环执行第二个步骤;
Slave的SQL线程会一直持续的观察relay日志文件中是否有改动,如果没有就继续监听;
如果发现relay中有变动,那么就获取变动的内容转换为SQL语句,并且把SQL语句在Salve的数据库中进行执行
主从配置可查看我写的这篇博客简单实践实现 MySQL 主从复制
比较一下基于GTID方式的复制和基于日志点的复制
基于日志点的复制:从主服务器的哪个二进制日志的偏移量进行增量同步,如果指定错误会造成遗漏或重复。
基于GTID的复制:从服务器会告诉主服务器,已经在从服务器上已经执行完了哪些gtid值,然后主库会把从库未执行的事务gtid值发送给从库执行。同一个事务只在指定的从库上执行一次。
GTID既全局事务ID,其保证为每一个在主上提交的事务在复制集群中可以生成一个唯一的ID
比较一下MMM和MHA两种高可用架构的优缺点
高可用架构都有如下的共同点:
- 对主从复制集群中的Master节点进行监控
- 自动的对Master进行迁移,通过VIP。
- 重新配置集群中的其它slave对新的Master进行同步
MMM架构:
需要两个Master,同一时间只有一个Master对外提供服务,可以说是主备模式。
资源 | 数量 | 说明 |
---|---|---|
主DB | 2 | 用于主备模式下的主主复制 |
从DB | 0~N台 | 可以根据需要配置N台从服务器 |
IP地址 | 2n+1 | N为mysql服务器的数量 |
监控用户 | 1 | 用户监控数据库状态的mysql用户(replication) |
代理用户 | 1 | 用于MMM代理端改变read_only状态 |
故障转移步骤:
- Slave服务器上的操作
- 完成原主上已经复制的日志恢复
- 使用Change Master命令配置新主
- 主服务器上操作
- 设置read_only关闭
- 迁移VIP到新主服务器
优点:
- 提供了读写VIP的配置,试读写请求都可以达到高可用
- 工具包相对比较完善,不需要额外的开发脚本
- 完成故障转移之后可以对MySQL集群进行高可用监控
缺点:
- 故障简单粗暴,容易丢失事务,建议采用半同步复制方式,减少失败的概率
- 目前MMM社区已经缺少维护,不支持基于GTID的复制
适用场景:
- 读写都需要高可用的
- 基于日志点的复制方式
MHA架构
资源 | 数量 | 说明 |
---|---|---|
主DB | 2 | 用于主备模式下的主主复制 |
从DB | 2~N台 | 可以根据需要配置N台从服务器 |
IP地址 | n+1 | N为mysql服务器的数量 |
监控用户 | 1 | 用户监控数据库状态的mysql用户(replication) |
代理用户 | 1 | 用于配置mysql复制的用户 |
MHA采用的是从slave中选出Master,故障转移:
从服务器:
- 选举具有最新更新的slave
- 尝试从宕机的master中保存二进制日志
- 应用差异的中继日志到其它的slave
- 应用从master保存的二进制日志
- 提升选举的slave为master
- 配置其它的slave向新的master同步
优点:
MHA除了支持日志点的复制还支持GTID的方式
同MMM相比,MHA会尝试从旧的Master中恢复旧的二进制日志,只是未必每次都能成功。如果希望更少的数据丢失场景,建议使用MHA架构。
缺点:MHA需要自行开发VIP转移脚本。
MHA只监控Master的状态,未监控Slave的状态
如何减小主从复制的延迟
主从延迟产生的原因及处理方法:
- 网络延迟
- 减小单次事务处理的数据量以减少产生的日志文件大小
- 减少主上所同步的Slave的数量
- 大事务
- 化大事务为小事务,分批更新数据
- 使用pt-online-schema-change工具进行DDL操作
- 单线程恢复
- 使用mysql5.7之后的多线程复制
- 使用MGR复制架构
说说你对MGR的认识
MGR(MySQL Group Replication)简称:MGR(组复制)。它是官方推出的一种基于Paxos协议的状态机复制,彻底解决了基于传统的异步复制和半同步复制中数据一致性问题无法保证的情况
MGR复制架构:
MGR复制实现原理:
MGR复制架构的优点:
- Group Replication组内成员基本无延迟
- 可以支持多写操作,读写服务高可用
- 数据强一致,可以保证不丢失事务
MGR复制架构的缺点:
- 只支持InnoDB存储引擎的表,并且每个月必须有一个主键
- 单主模式下很难确认下一个PRIMARY
- 只能用在gtid模式的复制形式下,且日志格式必须为row
MGR复制架构的适用场景:
- 对主从延迟十分敏感的应用场景
- 希望可以对读写提供高可用的场景
- 希望可以保证数据强一致的场景
如何解决数据库读/写负载大的问题
解决读负载大问题步骤:
- 为原DB增加Slave服务器
- 进行读写分离,把读分担到Slave
- 增加数据库中间层,进行负载均衡
解决写负载大问题:
- 进行分库分表
备份恢复类问题
在之前的工作中是如何对数据库进行备份的?
常用的备份工具:
名称 | 特点 |
---|---|
mysqldump | 最常用的逻辑备份工具,支持全量备份及条件备份 |
mysqlpump | 多线程逻辑备份工具,mysqldump的增强版本 |
xtrabackup | Inoodb在线物理备份工具,支持多线程和增量备份 |
mysqldump的优点:
- 备份结果为可读的SQL文件,可用于跨版本跨平台恢复数据
- 备份文件的尺寸小于物理备份,便于长时间存储
- mysql发行版自带工具,无需安装第三方软件
mysqldump的缺点:
- 只能单线程执行备份恢复任务,备份恢复速度较慢
- 为完成一致性备份需要对备份表加锁,容易造成阻塞
- 会对Innodb Buffer Pool造成污染
mysqlpump的优点:
- 语法同mysqldump高度兼容,学习成本低
- 支持基于库和表的并行备份,可以提高逻辑备份的性能
- 支持使用ZLIB和Lz4算法对备份进行压缩
mysqlpump的缺点:
- 基于表进行并行备份,对于大表来说性能较差
- 5.7.11之前版本不支持一致性并行备份
- 会对Innodb Buffer Pool造成污染
xtrabackup的优点:
- 支持Innodb存储引擎的在线热备份,对Innodb缓冲没有影响
- 支持并行对数据库的全备和增量备份
- 备份和恢复效率比逻辑备份高
xtrabackup的缺点:
- 做单表恢复时比较复杂
- 完整的数据文件备份,故备份文件比逻辑备份大
- 对跨平台和数据库版本的备份恢复支持度不如逻辑备份
如何对mysql进行增量备份和恢复
可查看我这里写的博客如何删库以后不跑路
如何对binlog进行备份
- 利用cp命令进行离线备份
- 使用mysqlbinlog命令在线时实备份
管理及监控类问题
说说你都对mysql进行过哪些监控?
性能类指标:
名称 | 说明 |
---|---|
QPS | 数据库每秒钟处理的请求数量 |
TPS | 数据库每秒钟处理的事务数量 |
并发数 | 数据库实例当前并行处理的会话数量 |
连接数 | 连接到数据库会话的数量 |
功能类指标:
名称 | 说明 |
---|---|
可用性 | 数据库是否可正常对外提供服务 |
阻塞 | 当前是否有阻塞的会话 |
死锁 | 当前事务是否产生了死锁 |
慢查询 | 时实慢查询监控 |
主从延迟 | 数据库主从延迟时间 |
主从状态 | 数据库主从复制链路是否正常 |
这些监控是如何实现的?
QPS(数据库每秒钟处理的请求数量)计算:
- show global status like ‘com%’
- sum(com_xxx)
- show global status like ‘Queries’
- QPS=(Queries2-Queries1)/时间间隔
TPS(每秒钟处理的事务数量)计算:
- show global status where Variable_name in (‘com_insert’,’com_delete’,’com_update’)
- Tc=com_insert+com_delete+com_update
- TPS=(Tc2-Tc1)/(time2-time1)
并发数计算:
- show global status like ‘Threads_running’
连接数计算:
- show global status like ‘Threads_connected’
报警阀值:- Threads_connected/max_connections > 0.8
Innodb缓存命中率:
- (Innodb_buffer_pool_read_requests - Innodb_buffer_pool_reads)/Innodb_buffer_pool_read_requests * 100%
- Innodb_buffer_pool_read_requests:从缓存池中读取的次数
- Innodb_buffer_pool_reads:表示从物理磁盘读取的次数
数据库可用性:
- 周期性连接数据库并执行select @@version
- Mysqladmin -uxxx -pxxx -hxxx ping
阻塞:
mysql < 5.7
select b.trx_mysql_thread_id as ‘被阻塞线程’,b.trx_query as ‘被阻塞SQL’,c.trx_mysql_thread_id as ‘阻塞线程’,c.trx_query as ‘阻塞SQL’,(UNIX_TIMESTAMP()-UNIX_TIMESTAMP(c.trx_started)) as ‘阻塞时间’ from information_schema.innodb_lock_waits a join information_schema.innodb_trx b on a.requesting_trx_id = b.trx_id join information_schema.innodb_trx c on a.blocking_trx_id = c.trx_id where (UNIX_TIMESTAMP()-UNIX_TIMESTAMP(c.trx_started)) > 30
mysql >= 5.7
select waiting_pid as ‘被阻塞的线程’,waiting_query as ‘被阻塞的SQL’,blocking_pid as ‘阻塞线程’,blocking_query as ‘阻塞SQL’,wait_age as ‘阻塞时间’,sql_kill_blocking_query as ‘建议操作’ from sys.innodb_lock_waits where (UNIX_TIMESTAMP()-UNIX_TIMESTAMP(wait_started)) > 30
监控慢查询:
- 通过慢查询日志监控
- 通过information_schema.
PROCESSLIST
表实时监控- select * from information_schema.processlist where time>60 and command <> ‘sleep’;
监控主从延时:
- pt-heartbeat –user=xx –password=xx -h master –create-table –database xxx –update –daemonize –interval=1
- pt-heartbeat –user=xx –password=xx -h slave –database crn –monitor –daemonize –log /tmp/slave_lag.log
监控主从状态:
- show slave status
可通过编写shell脚本并执行定时任务对数据库进行监控
优化及异常处理
请列举三个你曾经处理过的让你印象深刻的问题
- 数据库服务器负载过大
- 慢查询造成的磁盘IO爆表
- 主从数据库数据不一致
处理过哪些mysql主从复制异常
你会从哪些方面对mysql数据库进行优化
本作品采用《CC 协议》,转载必须注明作者和本文链接
大佬有相关书籍推荐吗
如果会了这些,大概能拿到多少k :flushed: :flushed: :flushed:
mark
有分表相关的嘛
有些甚至看不懂了😇