结构与访问过程
MySQL = 客户端 + 服务端
客户端 = Connection(语言连接器例如:PHP-pdo,MySQLi)
服务端 = SQL层 + 存储引擎层
SQL层 = 链接/线程处理 + 查询缓存 + 分析器 + 优化器
存储引擎 = InnoDB + MariaDB + ...
一、系统文件
MySQL物理文件类型
日志文件主要包括:
1. 错误日志(Error Log)
2. 二进制日志(Binary Log)
3. 事务日志(InnoDB redo Log & undo Log)
4. 慢查询日志(Slow Query Log)
5. 查询日志(Query Log)
数据库文件
1. '.frm'文件
2. '.MYD'文件
3. '.MYI'文件
4. '.ibd'文件和'.ibdata'文件
其他配置文件
1. 系统配置文件(my.ini或者my.cnf)
2. pid,err文 件
3. socket文 件
二、锁机制
1. MyISAM 和 Memory 存储引擎使用的是表级锁,BDB 引擎使用的是页级锁,也支持表级锁。
2. InnoDB 存储引擎既支持行级锁,也支持表级锁,默认情况下使用行级锁。
所谓表级锁,它直接锁住的是一个表,开销小,加锁快,不会出现死锁的情况,锁定粒度大,发生锁冲突的概率更高,并发度最低。
所谓行级锁,它直接锁住的是一条记录,开销大,加锁慢,发生锁冲突的概率较低,并发度很高。
所谓页级锁,它是锁住的一个页面,它的开销介于表级锁和行级锁中间,也可能会出现死锁,锁定粒度也介于表级锁和行级锁中间,并发度也介于表级锁和 行级锁中间。
行级锁更适合大量按照索引条件并发更新少量不同的数据,同时还有并发查询的应用
2.1. 行级锁
1. 行级锁本身与表级锁的实现差别就很大,而事务的引入也带来了很多新问题,尤其是事务的隔离性,与锁机制息息相关。
2. 对于事务的基本操作,对于不同隔离级别可能引发的问题,像脏读、不可重复读等问题。
3. 数据库实现事务隔离的方式,基本可以分为两种:
(1)在操纵数据之前,先对其加锁,防止其他事务对数据进行修改。这就需要各个事务串行操作才可以实现。
(2)不加任何锁,通过生成一系列特定请求时间点的一 致性数据快照,并通过这个快照来提供一致性读取
4. 上面的第二种方式就是数据多版本并发控制,也就是多版本数据库,一般简称为 MVCC 或者 MCC,它是 Multi Version Concurrency Control 的简写。
5. 数据库的事务隔离越严格,并发的副作用就越小,当然付出的代价也就越大,因为事务隔离机制实质上是使得事务在一定程度上”串行化”,这与并行是矛盾的
共享锁语句
select * from table_name lock in share mode;
排他锁语句
select * from table_name for update;
2.2 死锁
为什么会死锁?
官方定义:两个事务都持有对方需要的锁,并且在等待对方释放,并且双方都不会释放自己的锁。
死锁如何处理?
等待,直到超时(innodb_lock_wait_timeout=50s)
发起死锁检测,主动回滚一条事务,让其他事务继续执行(innodb_deadlock_detect=on)
由于性能原因,一般都是使用死锁检测来进行处理死锁。
收集死锁信息:
利用命令 SHOW ENGINE INNODB STATUS查看死锁原因。
调试阶段开启 innodb_print_all_deadlocks,收集所有死锁日志。
减少死锁:
使用事务,不使用 lock tables 。
保证没有长事务。
操作完之后立即提交事务,特别是在交互式命令行中。
如果在用 (SELECT ... FOR UPDATE or SELECT ... LOCK IN SHARE MODE),尝试降低隔离级别。
修改多个表或者多个行的时候,将修改的顺序保持一致。
创建索引,可以使创建的锁更少。
最好不要用 (SELECT ... FOR UPDATE or SELECT ... LOCK IN SHARE MODE)。
如果上述都无法解决问题,那么尝试使用 lock tables t1, t2, t3 锁多张表
三、事务
事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永远更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的 单元,可以简化错误恢复病史应用程序更加可靠。一个逻辑共奏单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性:
1. 原子性(A) 对于数据修改,要么全部都执行,要么全都不执行。
2. 隔离性(C) 在所有的操作没有执行完毕之前,其他会话不能够看到中间改变的过程
3. 一致性(I) 事务发生前和发生后,根据数据的规则,总额应该匹配
4. 持久性(D) 事务一旦被提交,其结果就是永久性的,系统崩溃也不会影响
四、 索引
索引的结构,建立索引的注意点,回表问题
4.0. 索引结构
平衡二叉树
索引的结构叶子片的数据存储,以及数据新增与修改后的结构调整过程,不同数据类型的处理
4.1. 索引类型
4.1.1. 主键索引和普通索引
innodb存储引擎 =》主键索引与普通区别就在于:主键索引找的时候数据在磁盘的存储位置,而普通索引查找的是主键索引的位置
myisam存储引擎 =》主键索引与普通索引查找都是数据在磁盘空间的存储位置
4.1.2. 单索引与联合索引:
单索引: 就是一个字段简历的索引
联合索引:就是多个字段建立的索引 (实际工作推荐使用联合索引)
4.1.3. 覆盖索引与回表
覆盖索引:就是查询的sql所有的字段都是在索引上
回表:就是sql获取的字段没有在普通索引上,就需要去查询主键索引因此存在回表问题 (需要关注,数据量查询 30% 以内)
4.2. 扩展 innodb的行锁实现原理 :
基于索引定位数据 -》 锁住数据
五、 架构演变
单体架构的问题
1. 数据库读写瓶颈问题;
2. 数据备份的问题;
3. 容灾处理问题;
4. 数据量剧增读写问题
5.1. 主从复制 (关注):
MySOL支持一台主服务器同时向多台从服务器进行复制操作,从服务器同时可以作为其他从服务器的主服务器,如果MySQL主服务器访问量比较大,可以通过复制数据,然后在从同各器上进行查询操作,从而降低主服 务器的访问压力,同时从服务器作为主服务器的备份,可以避免主服务器因为故障数据丢失的问题。
延时问题,实现原理,搭建过程
主从MySQL好处:
1. 性能问题--不一定提高;
2. 数据冗余
注意:主从无法提高数据库的读写速度
5.2. 集群
延时问题,故障转移过程
MySQL集群实则是在主从的基础上进行扩展,如双主双从的架构,再利用Keepalived进行MySQL集群负载均衡与故障转移;
分库分表
IO瓶颈
第一种:磁盘读IO瓶颈,热点数据太多,数据库缓存放不下,每次查询时会产生大量的IO,降低查询速度 -> 分库和垂直分表。
第二种:网络IO瓶颈,请求的数据太多,网络带宽不够 -> 分库。
mysql io 定位工具 :https://yq.aliyun.com/articles/603735?utm_content=m_1000003799
CPU瓶颈
第一种:SQL问题,如SQL中包含join,group by,order by,非索引字段条件查询等,增加CPU运算的操作 -> SQL优化,建立合适的索引,在业务Service层进行业务计算。
第二种:单表数据量太大,查询时扫描的行太多,SQL效率低,CPU率先出现瓶颈 -> 水平分表。