DBA:

一高可用架构:

1.MHA:通过manager节点来管理主从主要为一主俩从的架构。优点:成熟稳定,对MySQL侵入性小。缺点:需要基于ssh免认证配置,存在一定安全隐患。无从节点读负载均衡功能。

2.mgr、pxc(基于galera,):多主架构的MySQL一般为三主架构,优点:数据一致性强,同步快。缺点:会损耗性能,多节点写入时锁冲突比较严重
3.主从(长城基本都是)、主从从(又称级联复制):级联复制:master服务器,只给一台slave服务器同步数据,然后slave服务器在向后端的所有slave服务器同步数据,降低master服务器的写压力,和复制数据的网络IO。容易产生数据不一致情况。
4.keeplived:长城大部分都是主从或者主从从+keeplived用它实现vip(第三方切换工具,我暂时没看copy一下)
①健康检查:
Keepalived起初是为LVS实际的,专门用来监控集群系统中各个服务节点的状态,它根据TCP/IP参考模型,在第三(网络层)、第四(传输层)、第五层(应用层),通过探测数据传送的状态判断节点状态是否正常。如果某个服务器节点出现异常,或者工作出现故障,Keepalived将检测到,并将出现的故障服务器节点从集群系统中剔除,这些工作全部是自动完成的,不需要人工干涉,需要人工完成的只是修复出现故障的服务节点
②故障切换:
后来Keepalived又加入了VRRP的功能,出现的目的是解决静态路由出现的单点故障问题,通过VRRP可以实现网络不间断稳定运行,因此Keepalvied一方面具有服务器状态检测和故障隔离功能,另外一方面也有HAcluster功能。
工作原理:Keepalived dirctors之间的故障切换转移,是通过VRRP协议来实现的。在keepalived directors正常工作时,主Directors节点会不断的向备节点广播心跳信息,用以告诉备节点自己还存活,当主节点发生故障时,备节点就无法继续检测到主节点的心跳,进而调用自身的接管程序,接管主节点的IP资源及服务。而当主节点恢复故障时,备节点会释放主节点故障时自身接管的IP资源及服务,恢复到原来的自身的备用角色

二、数据库备份与恢复:

mysqldump:逻辑备份,以sql文件方式储存。
xtrabackup:物理备份
1.逻辑备份
逻辑备份就是对数据库对象(如库表、存储过程等)进行导出工作,还原时导入备份文件;

2.物理备份
物理备份就是转储数据库相关物理文件(如数据、日志文件等),当数据库发生故障,可以使用这些备份文件进行还原;

3.优缺点
当数据量大时,逻辑备份还原速度慢,需要数据库加载和解释语句等,同时逻辑备份有助于避免数据损坏:若磁盘驱动器有故障而需要原始文件时,可能得到一个损坏的备份;

而物理备份不需要执行语句,直接还原数据库文件,速度较快;但是备份文件可能较大

全量备份:增量备份:差异备份。
一般都是采用全量备份加增量备份的方式。增量备份和差异的区别自己查下吧。

备份恢复:

先恢复全量备份,然后增量备份追到最近时间点,如果还需要恢复,就使用binlog日志恢复(记录MySQL操作的二进制文件),如果错误操作涉及回滚,使用binlog2sql(py插件)可以回滚语句。

三、mysql技术点:

1.隔离级别:
READ UNCOMMITTED
可读取到未提交数据,产生脏读
READ COMMITTED
可读取到提交数据,但未提交数据不可读,产生不可重复读,即可读取到多个提交数据,导致每次读取数据不一致
REPEATABLE READ
可重复读,多次读取数据都一致,产生幻读,即读取过程中,即使有其它提交的事务修改数据,仍只能读取到未修改前的旧数据。此为MySQL默认设置
SERIALIZABLE
可串行化,未提交的读事务阻塞修改事务(加读锁,但不阻塞读事务),或者未提交的修改事务阻塞其它事务的读写(加写锁,其它事务的读,写都不可以执行)。会导致并发性能差。
2.MVCC;(我没注意过,但是看有公司要求了解这个和隔离级别有关系)
多版本并发控制,其实指的是一条记录会有多个版本,每次修改记录都会存储这条记录被修改之前的版本,多版本之间串联起来就形成了一条版本链。
这样不同时刻启动的事务可以无锁地获得不同版本的数据(普通读)。此时读(普通读)写操作不会阻塞,写操作可以继续写,无非就是多加了一个版本,历史版本记录可供已经启动的事务读取。

面试官:MVCC 用来实现哪几个隔离级别?

我:用来实现读已提交和可重复读。首先隔离级别如果是读未提交的话,直接读最新版本的数据就行了,压根就不需要保存以前的版本。可串行化隔离级别事务都串行执行了,所以也不需要多版本,因此 MVCC 是用来实现读已提交和可重复读的。

面试官:那为什么需要 MVCC ?如果没有 MVCC 会怎样?

我:如果没有 MVCC 读写操作之间就会冲突。想象一下有一个事务1正在执行,此时一个事务2修改了记录A,还未提交,此时事务1要读取记录A,因为事务2还未提交,所以事务1无法读取最新的记录A,不然就是发生脏读的情况,所以应该读记录A被事务2修改之前的数据,但是记录A已经被事务2改了呀,所以事务1咋办?只能用锁阻塞等待事务2的提交,这种实现叫 LBCC。

3.存储结构存储引擎:只了解innodb就行
InnoDB引擎特点:
行级锁
支持事务,适合处理大量短期事务
读写阻塞与事务隔离级别相关
可缓存数据和索引
支持聚簇索引
崩溃恢复性更好
支持MVCC高并发
从MySQL5.5后支持全文索引
从MySQL5.5.5开始为默认的数据库引擎

支持事务:事务的特性acid:原子性,一致性,隔离性,持久性

原子性是指一个事务的所有操作不可分割,要么全部成功,要么全部失败。原子性是依靠undo.log来实现的,该日志会记录事务执行的SQL,在事务某一操作执行失败时,会通过undo.log进行反向补偿,回到之前的状态。

一致性是指事务执行前后,数据库的状态是一致的,表现在没有违反数据库的完整性(实体,域,参照)等等,事务的其他三大特性保证了事务的一致性。

实体完整性:是对关系中的记录唯一性,也就是主键的约束。

域完整性:域完整性是对数据表中字段属性的约束,包括字段的类型,缺省值,是否非空等,它确保不会输入无效的值。

参照完整性:参照完整性是对关系数据库中建立关联关系的数据表间数据参照引用的约束,也就是对外键的约束,外键必须是另一个关系的主键有效值,或者是NULL

隔离性是指事务并发时,各个事务对数据的操作对其他事务对该数据的读取不能产生影响,事务的隔离性是通过锁和mvcc来实现,写写操作通过锁来实现,MySQL的锁包括行锁,表锁,间隙锁等,写读操作通过MVCC来实现。

持久性是指事务操作的数据不会丢失,innodb通过force log at commit机制实现事务的持久性,即在事务提交的时候,必须先将该事务的所有事务日志写入到磁盘上的redo log file和undo log file中进行持久化。首先,MySQL通过缓存来减少磁盘的IO操作,提高效率,但缓存是不安全的,一旦断电,就会导致数据的丢失,为了解决这个问题,所以需要redo.log,事务在修改数据时,会将SQL写到redo.log,再写到缓存中,这样就保证了事务的持久性。

4:日志:
MySQL 支持丰富的日志类型,如下:
事务日志:transaction log
事务日志的写入类型为"追加",因此其操作为"顺序IO";通常也被称为:预写式日志 write ahead logging
事务日志文件: ib_logfile0, ib_logfile1
错误日志 error log
通用日志 general log
慢查询日志 slow query log
二进制日志 binary log
中继日志 reley log,在主从复制架构中,从服务器用于保存从主服务器的二进制日志中读取的事件

事务日志:transaction log
redo log:实现 WAL(Write Ahead Log) ,数据更新前先记录redo log
undo log:保存与执行的操作相反的操作,用于实现rollback
事务型存储引擎自行管理和使用,建议和数据文件分开存放

5.锁机制;
锁类型:
读锁:共享锁,也称为 S 锁,只读不可写(包括当前事务) ,多个读互不阻塞
写锁:独占锁,排它锁,也称为 X 锁,写锁会阻塞其它事务(不包括当前事务)的读和写
S 锁和 S 锁是兼容的,X 锁和其它锁都不兼容,举个例子,事务 T1 获取了一个行 r1 的 S 锁,另外事务 T2 可以立即获得行 r1 的 S 锁,此时 T1 和 T2 共同获得行 r1 的 S 锁,此种情况称为锁兼容,但是另外一个事务 T2 此时如果想获得行 r1 的 X 锁,则必须等待 T1 对行 r1 锁的释放,此种情况也称为锁冲突
锁粒度:
表级锁:MyISAM
行级锁:InnoDB
实现
存储引擎:自行实现其锁策略和锁粒度
服务器级:实现了锁,表级锁,用户可显式请求
分类:
隐式锁:由存储引擎自动施加锁
显式锁:用户手动请求
锁策略:在锁粒度及数据安全性寻求的平衡机制

6索引:
①:索引优化:
独立地使用列:尽量避免其参与运算,独立的列指索引列不能是表达式的一部分,也不能是函数的参数,在where条件中,始终将索引列单独放在比较符号的一侧,尽量不要在列上进行运算(函数操作和表达式操作)

左前缀索引:构建指定索引字段的左侧的字符数,要通过索引选择性(不重复的索引值和数据表的记录总数的比值)来评估,尽量使用短索引,如果可以,应该制定一个前缀长度

多列索引:AND操作时更适合使用多列索引,而非为每个列创建单独的索引

选择合适的索引列顺序:无排序和分组时,将选择性最高放左侧

只要列中含有NULL值,就最好不要在此列设置索引,复合索引如果有NULL值,此列在使用时也不会使用索引

对于经常在where子句使用的列,最好设置索引

对于有多个列where或者order by子句,应该建立复合索引

对于like语句,以 % 或者 _ 开头的不会使用索引,以 % 结尾会使用索引

尽量不要使用not in和<>操作,虽然可能使用索引,但性能不高

不要使用RLIKE正则表达式会导致索引失效

查询时,能不要就不用,尽量写全字段名,比如:select id,name,age from students;

大部分情况连接效率远大于子查询

在有大量记录的表分页时使用limit

对于经常使用的查询,可以开启查询缓存

多使用explain和profile分析查询语句

查看慢查询日志,找出执行时间长的sql语句优化

②索引查看:EXPLAIN 执行语句之前加入explain可以看到执行计划。

使用profile工具:
可以查看语句执行时间和cpu占用情况。

四、故障问题处理。

1、主从不一致:①跳过主从,②重新配置从库,手动复制主库过去。(可以使用pt工具分析不一致的表,单纯同步几个表,减少恢复量)

2、MySQL数据库卡顿
1)一般来讲,排除高并发的因素,还是要找到导致你CPU过高的哪几条在执行的SQL,show processlist语句,查找负荷最重的SQL语句,优化该SQL,比如适当建立某字段的索引;

2)打开慢查询日志,将那些执行时间过长且占用资源过多的SQL拿来进行explain分析,导致CPU过高,多数是GroupBy、OrderBy排序问题所致,然后慢慢进行优化改进。比如优化insert语句、优化group by语句、优化order by语句、优化join语句等;

3)考虑定时优化文件及索引;

4)定期分析表,使用optimize table;

5)优化数据库对象;

6)考虑是否是锁问题;

7)调整一些MySQL Server参数,比如key_buffer_size、table_cache、innodb_buffer_pool_size、innodb_log_file_size等;

8)如果数据量过大,可以考虑使用MySQL集群或者搭建高可用环境。

9)可能由于内存latch(泄露)导致数据库CPU高

10)在多用户高并发的情况下,任何系统都会hold不住,所以使用缓存是必须的,使用memcached或者redis缓存都可以;

11)看看tmp_table_size大小是否偏小,如果允许,适当的增大一点;

12)如果max_heap_table_size配置的过小,增大一点;

13)mysql的sql语句睡眠连接超时时间设置问题(wait_timeout)

14)使用show processlist查看mysql连接数,看看是否超过了mysql设置的连接数

基本的mysql方面就这样,SQL方面主要是索引设计、

下面是MySQL规范:

基础规范
(1)必须使用InnoDB存储引擎
解读:支持事务、行级锁、并发性能更好、CPU及内存缓存页优化使得资源利用率更高
(2)使用UTF8MB4字符集
解读:万国码,无需转码,无乱码风险,节省空间,支持表情包及生僻字
(3)数据表、数据字段必须加入中文注释
解读:N年后谁知道这个r1,r2,r3字段是干嘛的
(4)禁止使用存储过程、视图、触发器、Event
解读:高并发大数据的互联网业务,架构设计思路是"解放数据库CPU,将计算转移到服务层",并发量
大的情况下,这些功能很可能将数据库拖死,业务逻辑放到服务层具备更好的扩展性,能够轻易实现"增
机器就加性能"。数据库擅长存储与索引,CPU计算还是上移吧!
(5)禁止存储大文件或者大照片
解读:为何要让数据库做它不擅长的事情?大文件和照片存储在文件系统,数据库里存URI多好。
命名规范
(6)只允许使用内网域名,而不是ip连接数据库
(7)线上环境、开发环境、测试环境数据库内网域名遵循命名规范
业务名称:xxx
线上环境:xxx.db
开发环境:xxx.rdb
测试环境:xxx.tdb
从库在名称后加-s标识,备库在名称后加-ss标识
线上从库:xxx-s.db
线上备库:xxx-sss.db
(8)库名、表名、字段名:小写,下划线风格,不超过32个字符,必须见名知意,禁止拼音英文混用
(9)库名与应用名称尽量一致,表名:t_业务名称_表的作用,主键名:pk_xxx,非唯一索引名:idx_xxx,唯
一键索引名:uk_xxx
表设计规范
(10)单实例表数目必须小于500
单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表。
说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表
(11)单表列数目必须小于30
(12)表必须有主键,例如自增主键
解读:
a)主键递增,数据行写入可以提高插入性能,可以避免page分裂,减少表碎片提升空间和内存的使用
b)主键要选择较短的数据类型, Innodb引擎普通索引都会保存主键的值,较短的数据类型可以有效的减
少索引的磁盘空间,提高索引的缓存效率
c) 无主键的表删除,在row模式的主从架构,会导致备库夯住
(13)禁止使用外键,如果有外键完整性约束,需要应用程序控制
解读:外键会导致表与表之间耦合,update与delete操作都会涉及相关联的表,十分影响sql 的性能,
甚至会造成死锁。高并发情况下容易造成数据库性能,大数据高并发业务场景数据库使用以性能优先
字段设计规范
(14)必须把字段定义为NOT NULL并且提供默认值
解读:
a)null的列使索引/索引统计/值比较都更加复杂,对MySQL来说更难优化
b)null 这种类型MySQL内部需要进行特殊处理,增加数据库处理记录的复杂性;同等条件下,表中有较多
空字段的时候,数据库的处理性能会降低很多
c)null值需要更多的存储空,无论是表还是索引中每行中的null的列都需要额外的空间来标识
d)对null 的处理时候,只能采用is null或is not null,而不能采用=、in、<、<>、!=、not in这些操作符
号。如:where name!='shenjian',如果存在name为null值的记录,查询结果就不会包含name为null
值的记录
(15)禁止使用TEXT、BLOB类型
解读:会浪费更多的磁盘和内存空间,非必要的大量的大字段查询会淘汰掉热数据,导致内存命中率急
剧降低,影响数据库性能
(16)禁止使用小数存储货币
解读:使用整数吧,小数容易导致钱对不上
(17)必须使用varchar(20)存储手机号
解读:
a)涉及到区号或者国家代号,可能出现+-()
b)手机号会去做数学运算么?
c)varchar可以支持模糊查询,例如:like"138%"
(18)禁止使用ENUM,可使用TINYINT代替
解读:
a)增加新的ENUM值要做DDL操作
b)ENUM的内部实际存储就是整数,你以为自己定义的是字符串?
索引设计规范
(19)单表索引建议控制在5个以内
(20)单索引字段数不允许超过5个
解读:字段超过5个时,实际已经起不到有效过滤数据的作用了
(21)禁止在更新十分频繁、区分度不高的属性上建立索引
解读:
a)更新会变更B+树,更新频繁的字段建立索引会大大降低数据库性能
b)"性别"这种区分度不大的属性,建立索引是没有什么意义的,不能有效过滤数据,性能与全表扫描类

(22)建立组合索引,必须把区分度高的字段放在前面
解读:能够更加有效的过滤数据
7.3.6 SQL使用规范
(23)禁止使用SELECT *,只获取必要的字段,需要显示说明列属性
解读:
a)读取不需要的列会增加CPU、IO、NET消耗
b)不能有效的利用覆盖索引
c)使用SELECT *容易在增加或者删除字段后出现程序BUG
(24)禁止使用INSERT INTO t_xxx VALUES(xxx),必须显示指定插入的列属性
解读:容易在增加或者删除字段后出现程序BUG
(25)禁止使用属性隐式转换
解读:SELECT uid FROM t_user WHERE phone=13812345678 会导致全表扫描,而不能命中phone索
引,猜猜为什么?(这个线上问题不止出现过一次)
(26)禁止在WHERE条件的属性上使用函数或者表达式
解读:SELECT uid FROM t_user WHERE from_unixtime(day)>='2017-02-15' 会导致全表扫描
正确的写法是:SELECT uid FROM t_user WHERE day>= unix_timestamp('2017-02-15 00:00:00')
(27)禁止负向查询,以及%开头的模糊查询
解读:
a)负向查询条件:NOT、!=、<>、!<、!>、NOT IN、NOT LIKE等,会导致全表扫描
b)%开头的模糊查询,会导致全表扫描
(28)禁止大表使用JOIN查询,禁止大表使用子查询
解读:会产生临时表,消耗较多内存与CPU,极大影响数据库性能
(29)禁止使用OR条件,必须改为IN查询
解读:旧版本Mysql的OR查询是不能命中索引的,即使能命中索引,为何要让数据库耗费更多的CPU帮助实施查询优化呢?
(30)应用程序必须捕获SQL异常,并有相应处理

一些常用的数据库工具:mycat用来读写分离、分库分表。
pt用来MySQL性能分析

另外还有redis :
了解一下 哨兵模式 cluster集群模式以及扩缩容等。