Mysql高级知识总结

Posted 狗哥狗弟齐头并进

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql高级知识总结相关的知识,希望对你有一定的参考价值。

关于Innodb存储引擎

1、Innodb存储引擎是基于磁盘存储的,使用缓冲池技术来提高数据库的整体性能。磁盘读取的数据会缓冲到缓冲池,以便下次使用。更新的时候先更新缓存池,然后再通过checkpoing机制刷新回磁盘。
2、Innodb存储引擎(内存层面)与Mysiam不同的地方有一个重要的就是Innodb不仅把索引缓存,同时也会缓存实际的数据。缓冲池可以完成数据的更新,减少了随机I/0的操作。尽可能提高缓存池的size,以保证操作再内存进行,再更新。
3、InnoDB存储引擎中,缓存池中页的大小默认为16KB,通过LRU算法来进行数据页的换进换出操作。缓存池不能存放新读取到的页时,会释放LRU列表中尾段的页。
InnoDB对LRU做了优化,因为,新读取的数据可能用一次就不用了,所以把新读取的数据放在midpoing就是中间位置。默认是5/8的位置上。机器重启之后,可以通过缓存预热,将热点数据缓存进来。避免了高峰期对磁盘的大量I/0。
4 change buffer的主要目的是将二级索引的数据缓存下来。聚簇索引通过主键id一次就可以查询到数据,但是非聚簇索引会回表二次查询。二级索引通常是非唯一的,插入的顺序也是随机的顺序。更新删除等操作都不是在临近的位置。所以,可以在写数据的时候,如果索引不在change buffer 就可以先创建一个change 缓存区,然后再慢慢的更新二级索引页与缓存区的同步。所以适用于写多读少的场景。比如日志的记录。
5 自适应哈希索引。Innodb会自动记录二次索引的查找,可以说是监控把,当二次索引被频繁的访问比如连续三次以上,就会认为是热点数据。通过B+Tree会构造自适应哈希索引。只适合用于等值查询,不适合模糊查询,和范围查询。
6 双写(页数据一页16KB,如果只写了一半宕机,会导致丢失。双写可以解决)
原理 : 每次写入一个page的时候,先把page 写到double write 缓冲池中。如果再写缓存池的时候出现意外,但是数据文件中原来的page不受影响。这样下次启动时可以通过redolog来进行数据恢复。如果缓存池写成功,就可以同步到磁盘上的page。Redolog是物理逻辑的,将存放的数据完整性与逻辑性相结合。物理表示记录的日志针对的是页的修改,为每个页上的操作单独记日志;逻辑表示记录日志的内容是逻辑的。
7 Innodb修改数据的流程。当我们想要修改DB上某一行数据的时候,InnoDB是把数据从磁盘中读取到内存中的缓存池中进行修改。修改之后就产生了脏页。Redolog可以解决脏页的问题。 Redolog分为重做日志缓冲,和重做日志文件。有一个类似版本号的数值。在宕机之后比较缓冲池中的版本号与数据页中是否一致,如果数据库中的版本号大于缓存池中,就不需要更新。
8 undo log 是MVCC事务特性的重要组成部分。当我们对记录做了变更操作的时候就产生undo记录。Undo记录默认被记录到系统表空间中。在Innodb中,insert操作在事务提交前只对当前事务可见,undo log在事务提交后就会被删除,因为新插入的数据没有历史版本,所以无需维护u n do log ,但是update delete就需要维护版本信息。多版本并发控制?终于理解了。

mysql事务和锁

Innodb默认情况下使用的是表级锁。
1、 事务中的所有SQL语句都被当做一个整体,要么全部执行成功,要么在其中么偶写操作执行失败后回滚到最初状态,就好像什么都没有发生过一样。
2、 原子性的保证是通过undo log日志也就是回滚日志来实现的,所有事务进行的修改都会记录到回滚日志中,然后对数据库中得对应行进行写入。回滚日志必须咸鱼数据持久化到磁盘上。
3、 原子性:整个事务中所有的操作要么全部执行成功,要么全部执行失败后回滚到最初的状态。 Undo log
一致性:数据库中的数据在事务操作前和事务处理后必须都满足业务规则约束,比如A和B账户总金额在转帐前和转账后必须保持一致。
隔离性:一个事务在提交之前所做出的操作能否为其他事务可见。由于不同的场景需求不同,因此针对隔离性来说有不同的隔离级别。 锁+MVCC
持久性:一旦提交,事务所做出的修改就会永久保存,即使数据库崩溃,修改的数据也不会丢失。 redo log 日志。
4 、事务隔离级别:
事务出现的现象:
(1)、 脏读: 当前事务读取到了别的事务中不可读取的其修改过的值。A读取事务B修改了的数据,但是B进行了回滚。
(2)、不可重复读:当前事务在读取同一个值时候,两次读取的数值不一致。
(3)、幻读:当前事务中读取到了其他事务提交的数据,出现了幻读,就跟中了迷药一样。
(4)、丢失更新,当两个事务在同一时刻对同一数据进行读取后,先后进行修改。导致第一次操作数据丢失。
事务的隔离级别:
(1)、读未提交:即使别的事务所做的修改并未提交,也能看到其修改的数据。并发性最高,但是隔离性和安全性最差。生产环境中不使用。会出现脏读。
(2)、读已提交:可以解决脏读的问题。只能读取已经提交事务的信息,但是当一个事务正在写,其他事务就会无法访问。但是却可能出现不可重复度。比如:事务A事先读取了数据,事务B紧接着更新并提交了事务,当事务A再次读取该数据时,数据已经发生改变。
(3)、可重复读:是指在一个事务内多次读取同一数据。假设在一个事务还没有结束时,另一个事务也访问同一数据,那么在第一个事务中的两次读取数据之间,即使第二个事务对数据进行了修改,第一个事务两次读到的数据也是一样的。这样在一个事务内,两次读取到的数据就是一样的。(读取数据的事务禁止写事务但允许读事务),写事务则禁止任何其他事务,这样即可以避免不可重复读和脏读,但是有时会出现幻读。
(4)、序列化:提供严格的事务隔离。要求事务序列化执行,一个接一个。不能并发执行。
Mysql默认的隔离级别是读已提交,
5 、InnoDB的锁机制
InnoDB的锁主要分为行级锁和表级锁。InnoDB的行级锁类型主要有共享锁X和排他锁S。也就是读锁和写锁。读锁允许持有读锁的事务读取行。写锁允许持有该锁的事务更新或删除行。 当在select语句都后面加 for update,Mysql会对查询结果中的每行都加排他锁。其他任何事务就不能对被锁定的行上加任何锁了。
意向锁(间隙锁):为了让行级锁和表级锁共存,为了防止DDL(数据库定义语言)和DML(数据库操作语言curd)的并发问题。是表级锁。
注意:只有通过索引条件检索数据才会使用。当条件上没有索引的时候,Innodb使用的是表级锁。
6 死锁
死锁产生的四个条件:
互斥条件:该资源任意时刻只能由一个线程占用
请求与保持条件:一个进程因请求一个资源而阻塞时,对已获得的资源保持不放
不剥夺条件:线程获取了资源,在未使用完之前不能被其他线程强行剥夺。
循环等待条件:若干进程之间形成了一种头尾相间的循环等待资源关系。
预防死锁:
1 破坏请求与保持条件:一次性申请所有的资源
2 破坏不剥夺条件:持有锁的线程,申请其他资源申请不到的时候,可以主动释放它占有的资源
3 破坏循环等待条件:申请资源的时候按照顺序去申请,然后再释放。

SQL语句性能优化

1 尽量避免使用select*并且加上limit限制。原因:服务器端和客户端在一次数据包的过程中数据包的大小可以自己定义,当我们传输的数据包,大于这个值,那么服务器就会拒绝接受更多的数据并且抛出异常。服务器的响应有很多,不能只取几条数据就完事了。所以当请求的数据 包超过了max_allowed_packet参数的时候。会出现问题。
2 查询语句中如果有任何不确定的函数,查询结果都不会缓存。因为QueryCache 缓存的是SQL语句以及结果集,而bufferpool缓存的是整张表的数据。
3 缓存失效:当数据表被修改,那么和这个数据表相关的全部cache都会无效并删除。如果数据表频繁更新,MySql的查询缓存系统会跟踪查询中涉及到的每个表。对于密集的写操作,可能会频繁的造成缓存失效,间接引发CPU飙升。所以另外一个优化的途径就是全面禁用QueryCache。
4 索引。
4.1 索引的原理。
索引是提高Mysql查询性能的一个重要途径。索引往往以索引文件的形式存储在磁盘上。这样的话,索引查找过程中就要产生磁盘I/0。适合索引的结构应该是尽可能少地执行磁盘I/0操作。
数据库采用B+Tree的原因是比BTree在提高了磁盘I/0的同时,并没有解决元素遍历效率低下的问题。B+Tree是一种多路搜索树。只要遍历椰子节点就可以实现整棵树的遍历。也也别适合带有范围的查找。
B+Tree的特点:非叶子节点不存储data,只存储索引key;只有叶子节点才存储data。所有的叶子节点由指针连接,并且按照键值的大小顺序排列。
4.2 聚簇索引和辅助索引、、
聚簇索引:叶子节点存放的是一整行的记录。
辅助索引:辅助索引的叶子节点并不包含行记录的全部数据,而是存储相应行数据的主键。通过辅助索引来查询数据的时候,Innodb存储引擎会遍历辅助索引找到主键,然后通过主键在聚集索引中找到完整的行记录数据。
主键一定是一个聚簇索引。如果一个表没有主键,那么取第一个唯一索引而且只含非空列作为主键。如果没有这样的列吗,就自己产生一个ID值。
SQL慢的优化思路:
开启慢查询日志,设置超过几秒为慢查询日志,抓取慢sql语句。通过explain查看执行计划,对慢sql语句分析,创建索引并调整语句,再查看执行计划,对比调优结果。
Set global slow_query_log=on。
SQL优化注意事项
1、主键不要进行类型转化
select name,phone from customer where id = ‘111’;
2、使用模糊查询的时候应该避免有前置%
a like ‘%123%’
3、范围查询的索引要放在联合索引的右侧
4、 not in 会使得索引失效,一般采用left join来优化
5、禁止使用 SELECT * 必须使用 SELECT <字段列表> 查询
因为会消耗更多的cpu和io资源
使用了
就无法使用覆盖索引
6、避免使用子查询,可以把子查询优化为 join 操作
通常子查询在in子句中,且子查询为简单SQL (不包含union、group by、order by、limit 从句) 时,才可以把子查询转化成关联查询进行优化。
why?
因为子查询往往是存放临时数据的,结果集存放在临时表,而临时表不会使用索引,也就是说子查询不会走索引,所以效率低,当结果集数量很大的时候,查询性能月迪。
由于子查询会产生大量的临时表,也没有索引。所以会消耗过多的CPU和IO资源,产生大量的慢查询。
7、避免使用join关联太多的表
8、 WHERE 从句中禁止对列进行函数转换和计算
对列进行函数转换或计算时会导致无法使用索引
创建索引的注意事项
1、选择合适的字段作为索引
不为null,优化比较难
被频繁查询的字段
被作为条件查询,顺序查询,分组查询的字段
2、被频繁更新的字段建议不加索引
因为更新字段得话,相应的索引也会被更新,会降低系统的性能
3、尽可能建立联合索引,而不是单列索引
因为索引是要占据磁盘空间的,可以简单理解为每个索引都对应一颗B+树。如果一个表的字段过多,索引过多,那么当这个表的数据到达一定的体量后。索引占据的空间很多。修改索引,耗费的时间也比较多。如果是联合索引,多个字段在一个索引上,会节约很大的磁盘空间,修改数据的操作频率也会提升。
4、注意避免冗余索引。
能命中 a 就不要再建立冗余索引
5、 字符串类型的字段可以加前缀索引。

以上是关于Mysql高级知识总结的主要内容,如果未能解决你的问题,请参考以下文章

Mysql高级知识总结

Mysql高级知识总结

个人总结的菜鸟教程|sql教程的知识点(SQL高级教程)

MySQL基础知识和常用命令总结

2021阿里Java高级面试题总结,GitHub已标星16k

Unity高级开发面向对象编程知识总结