1.基础架构:一条sql查询是如何执行的?
MySQL分为server层和存储引擎层两部分。
server包含:
连接器:权限管理。长连接会出现oom,MySQL临时使用的内存是管理在链接对象里面的,[定期]断开链接才会释放内存。
查询缓存:查询缓存利大于弊,失效非常频繁,导致命中率非常低,除非是一张静态表。8.0开始没有这个功能了。
分析器:sql分析,校验语法。
优化器:多个索引选择,jion链接顺序等
执行器:校验权限,调用innoDB,调用引擎接口下一行,返回所有满足条件的结果[引擎扫描行数跟执行器的执行行数不同]
存储引擎:支持innoDb和MyISAM
2.日志系统:一条sql更新语句是如何执行的?
与查询的区别:
相同点:查询流程执行得到结果行。
区别:执行更新,redo log和bin log
redoLog:innoDb配置4个redoLog文件,每个大小1G。先写redoLog,后写磁盘。
有了redo-logMySQL异常重启,不会丢失数据,crash-safe。
物理日志
记录的是在某个页上做了什么修改
循环写,空间大小固定
binLog:属于server层日志。
逻辑日志
记录这个语句的原始逻辑
追加写
update流程:
比如ID=2这行数据结果,这行所在的数据页在内存中,直接给执行器,否则从磁盘读入再给执行器。
执行器操作[比如N+1],得到新的一行数据,再调用引擎写入该行数据。
引擎更新到内存中同时记录到redoLog,处于prepare状态。
通知执行器可以随时提交事务。
执行器生成操作binlog并把binlog写入磁盘
执行器调用引擎提交事务接口,引擎修改redolog状态为commit
更新完成。
为什么要两阶段提交?先写binlog,后写redolog?先写redolog后写binlog?
3.事务隔离:为什么你改了我还看不见?
特性:原子性,隔离性,一致性,持久性
隔离级别问题:脏读、不可重复读、幻读
隔离级别:读未提交、读提交、可重复读、串行化
4.深入浅出索引
a.索引的常见模型:
哈希表:新增快,区间查询慢,适用于等值查询。
有序数组:范围查询和等值查询性能优秀,插入效率差。
搜索树:
二叉树:搜索效率最高
N叉树:减少磁盘io次数。
B+树:
索引类型分为:主键索引和非主键索引:
主键索引的叶子节点存的是整行数据。主键索引又称聚簇索引。
非主键索引叶子节点的内容是主键的值。非主键索引也称为二级索引。
b.索引维护:
页的分裂和合并
自增主键符合不挪动其它记录,也不会触发叶子节点的分裂。
主键索引的长度越小,普通索引的叶子节点越小。
覆盖索引:查询的列被索引覆盖,提升查询性能。
最左前缀原则:ABC组合索引,ABC,AB, A是有效的,它根据第一个值A创建的索引,索引指向B,B指向C;如果从第二个值开始,直接不走索引。
索引下推:去掉不符合条件的记录
5.全局锁、表锁、行锁:
1.全局锁:
使用场景:做全库逻辑备份。mysqldump
2.表级锁:
1.一种是表锁,
2.一种是元数据锁(meta data lock,MDL)
如何安全地给小表加字段?
ALTER TABLE tbl_name NOWAIT add column ...
ALTER TABLE tbl_name WAIT N add column ...
3.行锁功过:怎么减少行锁对性能的影响?
1.事务的可重复读的能力是怎么实现的?--todo
行锁的劣势:开销大;加锁慢;会出现死锁
行锁的优势:锁的粒度小,发生锁冲突的概率低;处理并发的能力强
加锁的方式:自动加锁。对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁;
对于普通SELECT语句,InnoDB不会加任何锁;
当然我们也可以显示的加锁:
共享锁:select * from tableName where … + lock in share more
排他锁:select * from tableName where … + for update
2.行锁优化
1 尽可能让所有数据检索都通过索引来完成,避免无索引行或索引失效导致行锁升级为表锁。
2 尽可能避免间隙锁带来的性能下降,减少或使用合理的检索范围。
3 尽可能减少事务的粒度,比如控制事务大小,而从减少锁定资源量和时间长度,从而减少锁的竞争等,提供性能。
4 尽可能低级别事务隔离,隔离级别越高,并发的处理能力越低。
3.行锁有三种算法,分别为:
1.Record Lock,单个记录上面的行锁
2.Gap Lock,锁定一个范围,但不包括自己
3.Next-Key Lock,锁定一个范围,包括自己
4.record lock和GAP lock next-key lock原理分析:
https://blog.csdn.net/weixin_39564755/article/details/110891596?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control
4.间隙锁:GAP
范围条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做”间隙(GAP)。
危害(坑):若执行的条件是范围过大,则InnoDB会将整个范围内所有的索引键值全部锁定,很容易对性能造成影响。
5.自增锁:
1.如果存在一个自增字段,MySQL会维护一个自增锁。
2.自增过程,https://xw.qq.com/cmsid/20200406A0NC8I00
3.innodb_autoinc_lock_mode:可以设定3个值,0,1,2
MySQL默认的配置为1。
6.MySQL性能优化:
优秀优化文章:https://www.cnblogs.com/sharpest/p/10390035.html
1.MYSQL优化主要分为以下四大方面:
1.设计:存储引擎,字段类型,范式与逆范式
1.存储引擎:
1.InnoDB存储引擎介绍:
1.Mysql版本>=5.5 默认的存储引擎,MySQL推荐使用的存储引擎。支持事务,行级锁定,外键约束。事务安全型存储引擎。更加注重数据的完整性和安全性。
2.存储格式:
创建一个test数据库,新建一张student表,选择存储引擎为innodb, 然后打开mysql的data下的test目录,发现有以下3个文件。
1.其中db.opt存放了数据库的配置信息,比如数据库的字符集还有编码格式。
2.student.frm是表结构文件,仅存储了表的结构、元数据(meta),包括表结构定义信息等。不论是哪个表引擎都会有一个frm文件。
3.student.ibd是表索引文件,包括了单独一个表的数据及索引内容。
3.数据按照主键顺序存储:
4.特定功能:事务、外键约束 : 都是为了维护数据的完整性。
5.innodb擅长事务、数据的完整性及高并发处理,不擅长快速插入(插入前要排序,消耗时间)和检索。
2.MyISAM存储引擎介绍:MySQL<= 5.5 MySQL默认的存储引擎,擅长与处理,高速读与写
1.存储方式
1.数据和索引分别存储于不同的文件中

2.数据的存储顺序为插入顺序(没有经过排序),插入速度快,空间占用小。
3.功能
a.全文索引支持。(mysql>=5.6时innodb 也支持)
b.数据的压缩存储。.MYD文件的压缩存储。
2、字段类型选择
字段类型应该要满足需求,尽量要满足以下需求。
1.尽可能小(占用存储空间少)、尽可能定长(占用存储空间固定)、尽可能使用整数。
3..表的设计合理化3nf
1.每一列是不可分割的原子数据
2.在1NF基础上,非码属性必须完全依赖于主码
3.在2NF的基础上,任何的非主属性不依赖于其他非主属性
2.功能:索引,缓存,分表分库。
1.索引:
1.索引分类:
1、普通索引,index:对关键字没有要求。
2.唯一索引,unique index:要求关键字不能重复。同时增加唯一约束。
3.主键索引,primary key:要求关键字不能重复,也不能为NULL。同时增加主键约束。
4.全文索引,fulltext key:关键字的来源不是所有字段的数据,而是从字段中提取的特别关键词。
2.索引操作:
1.散列值小的列不宜建立索引
2.索引不需要太多
3.空值字段和<>like%前,函数操作会导致索引失效,or的两端都要使用索引才能生效
4.经常增删的表不宜建立索引
5.索引下推,最左原则,覆盖索引,前缀索引
6.尽量使用主键索引,where和order by字段建立索引。
7.explain执行计划
2.查询缓存
3.分区分表
1.水平分表:创建n个相同的表结构,
2.垂直分表:创建热点字段和非热点字段不同的表
3.架构:主从复制,读写分离,负载均衡。

4.SQL优化:测试,经验。
30条sql优化经验:https://www.cnblogs.com/sharpest/p/10390043.html
1.对于并发性的SQL
少用(不用)多表操作(子查询,联合查询),而是将复杂的SQL拆分多次执行。如果查询很原子(很小),会增加查询缓存的利用率。
2.大量数据的插入
多条 insert或者Load data into table(从文件里载入数据到表里)
建议,先关闭约束及索引,完成数据插入,再重新生成索引及约束。
针对innodb,步骤:
Drop index, drop constraint 删除索引及约束,要保留主键
Begin transaction|set autocommit=0; 开启事务,不让他自动提交
[数据本身已经按照主键值排序]
大量的插入
Commit;
Add index, add constraint
3.分页
分页假定Limit offset, size; size = 10;基数越大性能越慢,将所有数据查出来,再去前n个。
4.随机选一些数据,不要使用Order by Rand()
会导致每条记录都执行rand(),成本很高!建议,通过mt_rand(),先确定的随机主键,再从数据表中获取数据。
5.慢查询日志的使用
1.查询语句:show variables like 'slow_query%'; show variables like '%long_query%';
2.开启日志
set global slow_query_log=1; set long_query_time=0.5;
3.执行SQL,查看:

6.join语句应该小表结果驱动大表结果。
2.EXPLAIN列的解释
1.id:选择标识符
2.select_type:表示查询的类型。
3.table:输出结果集的表
4.partitions:匹配的分区
5.type:表示表的连接类型
6.possible_keys:表示查询时,可能使用的索引
7.key:表示实际使用的索引
8.key_len:索引字段的长度
9.ref:列与索引的比较
10.rows:扫描出的行数(估算的行数)
11.filtered:按表条件过滤的行百分比
12.Extra:执行情况的描述和说明
1.Distinct
一旦MYSQL找到了与行相联合匹配的行,就不再搜索了
2.Not exists
MYSQL优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,就不再搜索了
3.Range checked for each Record(index map:#)
没有找到理想的索引,因此对于从前面表中来的每一个行组合,MYSQL检查使用哪个索引,并用它来从表中返回行。这是使用索引的最慢的连接之一
4.Using filesort
看到这个的时候,查询就需要优化了。MYSQL需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行。
6.MySQL主从同步原理

1.主从同步关键词:
1.主数据服务器:主要用来从业务服务写入数据或者修改更新数据
2.从数据服务器:主要用来读取业务所需要的数据
3.二进制日志:用来存储写入以及更新的数据信息
4.中继日志:承接主服务器数据信息,转存在从服务器上
5.I/O线程:监听主服务器是否发生数据更改的行为
6.SQL线程:将主服务器数据更改的数据从中继日志文件中读取数据写入到从数据服务器中
原文链接:https://blog.csdn.net/sinat_38798245/article/details/88351160
2.同步原理:
1.当主数据服务器master进行写入数据或者更新数据操作的时候,数据更改会记录在二进制日志(binary log file)中;
2.主服务器master与从服务器slave进行通讯的是I/O线程,它将修改的数据异步复制写入到slave服务器的中继日志(relay log file)中;
3.从服务器slave与中继日志之间通信使用SQL线程,SQL线程可以异步从中继日志中读取数据后再写入到自己的数据库中,就完成了数据的主从同步功能。
3.从服务器slave为什么不能直接存储二进制日志文件里面的数据?
个人理解的原因是本来做数据的主从同步就是为了让计算机快速的进行读写操作,而且是大批量的数据,一旦大量数据进行写入或者更新数据,从数据库slave如果直接从二进制日志来接收,数据是以队列形式进行传输的,若队列的数据没有快速处理,堆积起来,从服务器可能也会崩溃宕机,所以从性能上考虑,从服务器slave创建了I/O线程对象将数据转到中继日志,起个缓存功能。