MySql重要知识梳理
作者:mmseoamin日期:2024-02-28

文章目录

  • 一.索引
    • 1.索引概述
    • 2.索引优缺点
    • 3. 索引结构
      • 为什么InnoDB存储引擎选择使用B+tree索引结构?
      • 4.索引分类
        • 思考InnoDB主键索引的B+tree高度为多高?
        • 5. 索引语法
          • 1.索引语法
          • 2.sql性能分析
            • 1.SQL执行频率
            • 2.慢查询日志
            • 3.explain执行计划
            • 3.索引使用规则
              • 1.最左前缀法则
              • 2.索引失效情况
              • 3.SQL提示
              • 4.覆盖索引&回表查询
              • 5.前缀索引
              • 6.单列索引与联合索引
              • 7.索引设计原则
              • 二.SQL优化
                • 1.插入优化
                • 2.主键优化
                  • 1.页分裂
                  • 2.页合并
                  • 3.主键设计原则
                  • 3.order by优化
                    • order by优化原则:
                    • 4.group by优化
                      • group by优化原则:
                      • 5.limit优化
                        • limit优化原则:
                        • 6.COUNT优化
                        • 7.update优化
                        • SQL优化总结
                        • 三.锁
                          • 1.全局锁
                            • 1.语法
                            • 2.特点
                            • 2.表级锁
                              • 介绍
                              • 1.表锁
                              • 2.元数据锁
                              • 3.意向锁
                              • 3.行级锁
                                • 介绍
                                • 1.行锁
                                  • 数据演示
                                  • 2.间隙锁&临键锁
                                    • 数据演示
                                    • 总结
                                    • 四.InnoDB引擎
                                      • 1.概述
                                      • 2.MySQL的架构图
                                        • 1.内存结构
                                        • 2.磁盘结构
                                        • 3.后台线程
                                        • 五.事务原理
                                          • 1.事务基础
                                          • 2.redo log
                                          • 2.undo log
                                          • 3.MVCC
                                            • 1.隐藏字段
                                              • 数据演示
                                              • 2.undolog版本链
                                                • 1.介绍
                                                • 2.版本链
                                                • 3.readview
                                                • 4.原理分析
                                                  • 1.RC隔离级别
                                                  • 2.RR隔离级别
                                                  • 5.事务总结

                                                    一.索引

                                                    1.索引概述

                                                    • 索引(index)是帮助MySQL高效获取数据的数据结构(有序)。数据之外,数据库系统还维护者满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现查找算法,这种数据结构就是索引。

                                                      MySql重要知识梳理,在这里插入图片描述,第1张

                                                      2.索引优缺点

                                                      优势劣势
                                                      提高数据检索的效率,降低数据库的IO成本(提高查询速度)索引列也是要占用空间的。
                                                      通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消耗。(提高排序速度)索引大大提高了查询效率,同时却也降低更新表的速度,如对表进行INSERT、UPDATE、DELETE时,效率降低。(因为要重新维护索引结构)

                                                      3. 索引结构

                                                      索引InnoDBMyISAMMemory
                                                      B+tree索引支持支持支持
                                                      Hash索引不支持不支持支持
                                                      R-tree索引不支持支持不支持
                                                      Full-text5.6版本之后支持支持不支持
                                                      我们平时所说的索引,如果没有特别指明,都是指B+树结构组织的索引。

                                                      MySql重要知识梳理,在这里插入图片描述,第2张

                                                      MySql重要知识梳理,在这里插入图片描述,第3张

                                                      MySql重要知识梳理,在这里插入图片描述,第4张

                                                      • mysqlB+tree优化

                                                        MySql重要知识梳理,在这里插入图片描述,第5张

                                                      • Hash索引

                                                        MySql重要知识梳理,在这里插入图片描述,第6张


                                                        Hash索引特点

                                                        1.Hash索引只能用于对等比较(=,in),不支持范围查询(between,>,<,…)

                                                        2.无法利用索引完成排序操作

                                                        3.查询效率高,通常只需要一次检索就可以了,效率通常要高于B+tree索引


                                                        存储引擎支持 在MySQL中,支持hash索引的是Memory引擎,而InnoDB中具有自适应hash功能,hash索引是存储引擎根据B+Tree索引在指定条件下自动构建的。

                                                        为什么InnoDB存储引擎选择使用B+tree索引结构?

                                                        • 相对于二叉树,层级更少,搜索效率高;
                                                        • 对于B-tree,无论是叶子节点还是非叶子节点,都会保存数据,这样导致一页中存储的键值对减少,指针跟着减少,要保存大量数据,只能增加树的高度,导致性能降低;
                                                        • 相比Hash索引,B+tree支持范围匹配以及排序操作;

                                                          4.索引分类

                                                          分类含义特点关键字
                                                          主键索引针对与表中主键创建的索引默认自动创建,只能有一个PRIMARY
                                                          唯一索引避免同一个表中某数据列中的值重复可以有多个UNIQUE
                                                          常规索引快速定位特定数据可以有多个
                                                          全文索引全文索引查找的是文本中的关键词,而不是比较索引中的值可以有多个FULLTEXT

                                                          在InnoDB存储引擎中,根据索引的存储形式,又可以分为以下两种:

                                                          分类含义特点
                                                          聚集索引(Clustered Index)将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据必须有,而且有一个
                                                          二级索引(Secondary Index)将数据与索引分开存储,索引结构的叶子节点关联的是对应的主键可以存在多个

                                                          聚集索引选取规则:

                                                          • 如果存在主键,主键索引就是聚集索引。
                                                          • 如果不存在主键,将使用第一个唯一(UNIQUE)索引作为聚集索引。
                                                          • 如果表没有主键,或没有合适的唯一索引,则InnoDDB会自动生成一个rowid作为隐藏的聚集索引。

                                                            MySql重要知识梳理,在这里插入图片描述,第7张

                                                            MySql重要知识梳理,在这里插入图片描述,第8张

                                                            思考InnoDB主键索引的B+tree高度为多高?

                                                            MySql重要知识梳理,在这里插入图片描述,第9张

                                                            由上看出来即使存储2000多万行的数据树的高度只有三层,可见检索效率是非常高效的。

                                                            5. 索引语法

                                                            1.索引语法

                                                            MySql重要知识梳理,在这里插入图片描述,第10张

                                                            2.sql性能分析

                                                            1.SQL执行频率

                                                            MySQL客户端连接成功后,通过show[session|global] status命令可以提供服务器状态信息。通过如下指令,可以查看当前数据库的 INSERT 、UPDATE、DELETE、SELECT的访问频次:

                                                            SHOW GLOBAL STATUS LIKE 'Com_______';
                                                            

                                                            MySql重要知识梳理,在这里插入图片描述,第11张

                                                            2.慢查询日志
                                                            • 慢查询日志记录了所有执行时间超过参数(long_query_time,单位:秒,默认10秒)的所有SQL语句的日志。MySQL的慢查询日志默认没有开启,需要在MySQL的配置文件(/etc/my.cnf)中配置如下信息:

                                                              查看慢sql日志是否开启信息

                                                              show variables like 'slow_query_log';
                                                              

                                                              MySql重要知识梳理,在这里插入图片描述,第12张

                                                              MySql重要知识梳理,在这里插入图片描述,第13张


                                                              profile详情

                                                              show profiles能够在做SQL优化时帮助我们了解时间都耗费到哪里去了。通过having_profiling参数,能够看到当前MySQL是否支持profile操作:

                                                              SELECT @@have_profiling;
                                                              

                                                              MySql重要知识梳理,在这里插入图片描述,第14张

                                                              默认profiling是关闭的,可以通过set语句在session/global级别开启profiling;

                                                              SHOW VARIABLES LIKE 'profiling';
                                                              

                                                              MySql重要知识梳理,在这里插入图片描述,第15张

                                                              开启命令

                                                              set profiling = 1;
                                                              

                                                              执行一系列的业务SQL的操作,可以通过如下指令查看指令的执行耗时

                                                              #查看每一条SQL的耗时基本情况
                                                              show profiles;
                                                              #查看指定query_id的SQL语句各个阶段的耗时情况
                                                              show profile for query query_id
                                                              #查看指定query_id的SQL语句CPU的使用情况
                                                              show profile cpu for query query_id
                                                              
                                                              3.explain执行计划

                                                              explain或则desc命令获取MySQL如何执行SELECT语句的信息,包括在SELECT语句执行过程中表如何连接和执行的顺序。

                                                              语法:

                                                              #直接在select语句之前加上关键字exlain/desc
                                                              EXPLAIN SELECT 字段列表 FROM 表名 WHERE 条件;
                                                              

                                                              MySql重要知识梳理,在这里插入图片描述,第16张

                                                              explain执行计划各字段含义:

                                                              • Id

                                                                select 查询的序列号,表示查询中执行select子句或则是操作表的顺序(id相同,执行顺序从上到下;id不同,值越大,越先执行)。

                                                                MySql重要知识梳理,在这里插入图片描述,第17张

                                                              • select_type

                                                                表示SELECT的类型,常见的取值有SIMPLE(简单表,即不使用表连接或则子查询)、PRIMARY(主查询,即外层的查询)、UNION(UNION中的第二个或则后面的查询语句)、SUBQUERY(SELECT/WHERE之后包括了子查询)等。

                                                              • type

                                                                表示连接类型,性能由好到差的连接类型为NULL,system、const、eq_ref、ref、range、index、all.

                                                              • possible_key

                                                                显示可能应用在这张表上的索引,一个或多个。

                                                              • Key

                                                                实际使用的索引,如果为NULL,则没有使用索引。

                                                              • Key_len

                                                                表示索引中使用的字节数,该值为索引字段最大可能长度,并非实际使用长度,在不损失精确性的前提下,长度越短越好。

                                                              • rows

                                                                MySQL认为必须要执行查询的行数,在innodb引擎的表中,是一个估计值,可能并不总是准确的。

                                                              • filtered

                                                                表示返回结果的行数占需读取行数的百分比,filtered的值越大越好。

                                                                3.索引使用规则

                                                                1.最左前缀法则

                                                                如果索引了多列(联合索引),要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列。如果跳跃某一列,索引将部分失效(后面的字段索引失效)

                                                                • 注意:如果多个索引列的话按照最左前缀描述需要从第一个索引列开始走索引,如果第一个复合索引没有被命中,后面的将不会走索引。
                                                                • 注意:如果索引列都被命中,但是顺序是乱的也会走复合索引。
                                                                • 注意:如果第一个索引列被命中,后面的索引列部分中断,索引列走的是复合索引的连续索引。

                                                                  范围查询

                                                                  联合索引中,出现范围查询(>,<),范围查询右侧的列索引失效。

                                                                  MySql重要知识梳理,在这里插入图片描述,第18张

                                                                  大于等于或则小于等于可以避免这种情况

                                                                  2.索引失效情况
                                                                  • 索引列运算

                                                                    不要在索引列上进行运算操作,索引将失效

                                                                    MySql重要知识梳理,在这里插入图片描述,第19张

                                                                  • 字符串不加引号

                                                                    字符串类型字段使用时,不加引号,索引将失效

                                                                    MySql重要知识梳理,在这里插入图片描述,第20张

                                                                  • 模糊查询

                                                                    如果仅仅是尾部模糊匹配,索引不会失效。如果是头部模糊匹配,索引将失效

                                                                    MySql重要知识梳理,在这里插入图片描述,第21张

                                                                  • or连接的条件

                                                                    用or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到。

                                                                    MySql重要知识梳理,在这里插入图片描述,第22张

                                                                  • 数据分布影响

                                                                    如果MySQL评估使用索引比全表更慢,则不使用索引。

                                                                    3.SQL提示

                                                                    SQL提示,是优化数据库的一个重要手段,简单来说,就是在SQL语句中加入一些人为的提示来达到优化操作的目的。

                                                                    MySql重要知识梳理,在这里插入图片描述,第23张

                                                                    4.覆盖索引&回表查询
                                                                    • 覆盖索引

                                                                      尽量使用覆盖索引(查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到),减少select *。

                                                                      知识贴士:

                                                                      1.using index condition:查找使用了索引,但是需要回表查询数据

                                                                      2.using where;using index:查找使用了索引,但是需要的数据都在索引列中能找到,所以不需要回表查询数据

                                                                      MySql重要知识梳理,在这里插入图片描述,第24张

                                                                      5.前缀索引

                                                                      当字段类型为字符串(varchar,text等)时,有时候需要索引很长的字符串,这会让索引变得很大,查询时,浪费大量的磁盘IO,影响查询效率。此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率。

                                                                      MySql重要知识梳理,在这里插入图片描述,第25张

                                                                      MySql重要知识梳理,在这里插入图片描述,第26张

                                                                      MySql重要知识梳理,在这里插入图片描述,第27张

                                                                      6.单列索引与联合索引

                                                                      单列索引:一个索引只包含单个列

                                                                      联合索引:一个索引包括多个列

                                                                      7.索引设计原则
                                                                      1. 针对数据量大,且查询比较频繁的表建立索引。
                                                                      2. 针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引。
                                                                      3. 尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。
                                                                      4. 如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。
                                                                      5. 尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率。
                                                                      6. 要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增删改的效率。
                                                                      7. 如果索引列不能存储NULL值,请在创建表时使用NOT NULL约束他。当优化器知道每列是否包含NULL值时,它可以更好地确定哪个索引最有效地用于查询。

                                                                      二.SQL优化

                                                                      1.插入优化

                                                                      • 批量插入
                                                                        Insert into tb_test values(1,'Tom'),(2,'Cat'),(3,'Jerry');
                                                                        
                                                                        • 手动提交事务
                                                                          start transaction;
                                                                          insert into tb_test values(1,'Tom'),(2,'Cat'),(3,'Jerry');
                                                                          insert into tb_test values(4,'Tom'),(5,'Cat'),(6,'Jerry');
                                                                          insert into tb_test values(7,'Tom'),(8,'Cat'),(9,'Jerry');
                                                                          commit;
                                                                          
                                                                          • 主键顺序插入

                                                                            主键顺序插入,性能要高于乱序插入。

                                                                            主键乱序插入 : 8 1 9 21 88 2 4 15 89 5 7 3
                                                                            主键顺序插入 : 1 2 3 4 5 7 8 9 15 21 88 89
                                                                            
                                                                            • 大批量插入数据

                                                                              如果一次性需要插入大批量数据(比如: 几百万的记录),使用insert语句插入性能较低,此时可以使

                                                                              用MySQL数据库提供的load指令进行插入。

                                                                              -- 客户端连接服务端时,加上参数 -–local-infile
                                                                              mysql --local-infile -u root -p
                                                                              -- 设置全局参数local_infile为1,开启从本地加载文件导入数据的开关
                                                                              set global local_infile = 1;
                                                                              -- 执行load指令将准备好的数据,加载到表结构中
                                                                              load data local infile '/root/sql1.log' into table tb_user fields
                                                                              terminated by ',' lines terminated by '\n' ;
                                                                              

                                                                              MySql重要知识梳理,在这里插入图片描述,第28张

                                                                              2.主键优化

                                                                              • 数据组织方式

                                                                                在InnoDB存储引擎中,表数据都是根据主键顺序组织存放的,这种存储方式的表称为

                                                                                索引组织表(index organized table IOT).

                                                                                MySql重要知识梳理,在这里插入图片描述,第29张

                                                                                1.页分裂

                                                                                页可以为空,也可以填充一半,也可以填充100%。每个页包含了2-N行数据(如果一行数据太大,会行溢出),根据主键排列。

                                                                                MySql重要知识梳理,在这里插入图片描述,第30张

                                                                                MySql重要知识梳理,在这里插入图片描述,第31张

                                                                                2.页合并

                                                                                当删除一行记录时,实际上记录并没有被物理删除,只是记录被标记(flaged)为删除并且它的空间变得允许被其他记录声明使用。

                                                                                当页删除的记录达到MERGE_THRESHOLD(默认为页的50%),InnoDB会开始寻找最靠前的页(前或后)看看是否可以将两个页合并以优化空间使用。

                                                                                MySql重要知识梳理,在这里插入图片描述,第32张

                                                                                MySql重要知识梳理,在这里插入图片描述,第33张

                                                                                MERGE_THRESHOLD:合并页的阈值,可以自己设置,在创建表或者创建索引时指定。

                                                                                3.主键设计原则

                                                                                • 满足业务需求的情况下,尽量降低主键的长度。
                                                                                • 插入数据时,尽量选择顺序插入,选择使用AUTO_INCREMENT自增主键。
                                                                                • 尽量不要使用UUID做主键或者是其他自然主键,如身份证号。
                                                                                • 业务操作时,避免对主键的修改。

                                                                                  3.order by优化

                                                                                  1. Using filesort:通过表的索引或全表扫描,读取满足条件的数据行,然后再排序缓冲区sort buffer中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫FileSort排序。
                                                                                  2. Using index:通过有序索引顺序扫描直接返回有序数据,这种情况即为using index,不需要额外排序,操作效率高。

                                                                                    MySql重要知识梳理,在这里插入图片描述,第34张

                                                                                    如果按照age和phone进行联合索引,但是排序的时候不按照age和phone进行进行查询,违背最左前缀法则也会不走索引查询

                                                                                  order by优化原则:
                                                                                  A. 根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则。

                                                                                  B. 尽量使用覆盖索引,避免查询使用select *,进行回表查询。

                                                                                  C. 多字段排序, 一个升序一个降序,此时需要注意联合索引在创建时的规则(ASC/DESC)。

                                                                                  D. 如果不可避免的出现filesort,大数据量排序时,可以适当增大排序缓冲区大小 sort_buffer_size(默认256k)。

                                                                                  4.group by优化

                                                                                  下面这个图是没有创建索引的分组查询语句

                                                                                  MySql重要知识梳理,在这里插入图片描述,第35张

                                                                                  创建一个联合索引

                                                                                  MySql重要知识梳理,在这里插入图片描述,第36张

                                                                                  根据profession查询可以看到已经走索引

                                                                                  MySql重要知识梳理,在这里插入图片描述,第37张

                                                                                  根据age分组查询

                                                                                  MySql重要知识梳理,在这里插入图片描述,第38张

                                                                                  如果仅仅根据age分组,就会出现 Using temporary ;而如果是 根据

                                                                                  profession,age两个字段同时分组,则不会出现 Using temporary。原因是因为对于分组操作,在联合索引中,也是符合最左前缀法则的。

                                                                                  group by优化原则:

                                                                                  A. 在分组操作时,可以通过索引来提高效率。

                                                                                  B. 分组操作时,索引的使用也是满足最左前缀法则的。

                                                                                  5.limit优化

                                                                                  在数据量比较大时,如果进行limit分页查询,在查询时,越往后,分页查询效率越低。

                                                                                  MySql重要知识梳理,在这里插入图片描述,第39张

                                                                                  MySql重要知识梳理,在这里插入图片描述,第40张

                                                                                  MySql重要知识梳理,在这里插入图片描述,第41张

                                                                                  因为,当在进行分页查询时,如果执行 limit 2000000,10 ,此时需要MySQL排序前2000010 记

                                                                                  录,仅仅返回 2000000 - 2000010 的记录,其他记录丢弃,查询排序的代价非常大 。

                                                                                  limit优化原则:

                                                                                  优化思路: 一般分页查询时,通过创建 覆盖索引 能够比较好地提高性能,可以通过覆盖索引加子查询形式进行优化。

                                                                                  MySql重要知识梳理,在这里插入图片描述,第42张

                                                                                  MySql重要知识梳理,在这里插入图片描述,第43张

                                                                                  6.COUNT优化

                                                                                  • MyISAM 引擎把一个表的总行数存在了磁盘上,因此执行 count(*) 的时候会直接返回这个数,效率很高; 但是如果是带条件的count,MyISAM也慢。
                                                                                  • InnoDB 引擎就麻烦了,它执行 count(*) 的时候,需要把数据一行一行地从引擎里面读出来,然后累积计数。

                                                                                    如果说要大幅度提升InnoDB表的count效率,主要的优化思路:自己计数(可以借助于redis这样的数据库进行,但是如果是带条件的count又比较麻烦了)。

                                                                                    count() 是一个聚合函数,对于返回的结果集,一行行地判断,如果 count 函数的参数不是NULL,累计值就加 1,否则不加,最后返回累计值。

                                                                                    用法:count(*)、count(主键)、count(字段)、count(数字)

                                                                                    MySql重要知识梳理,在这里插入图片描述,第44张

                                                                                    按照效率排序的话,count(字段) < count(主键 id) < count(1) ≈ count(),所以尽

                                                                                    量使用 count()。

                                                                                    7.update优化

                                                                                    course表原始数据

                                                                                    MySql重要知识梳理,在这里插入图片描述,第45张

                                                                                    在第一个cmd窗口开启事务并且对name为Spring的记录进行修改

                                                                                    MySql重要知识梳理,在这里插入图片描述,第46张

                                                                                    在第二个cmd窗口开启事务对name=Hadoop进行修改,发现出现阻塞

                                                                                    MySql重要知识梳理,在这里插入图片描述,第47张

                                                                                    第一个cmd窗口提交事务的时候第二个cmd窗口成功修改

                                                                                    MySql重要知识梳理,在这里插入图片描述,第48张

                                                                                    当我们开启多个事务,在执行上述的SQL时,我们发现行锁升级为了表锁。 导致该update语句的性能大大降低。


                                                                                    查看索引结构发现name没有创建索引,对name创建索引

                                                                                    MySql重要知识梳理,在这里插入图片描述,第49张

                                                                                    然后在cmd执行命令发现不会把行锁升级为表锁

                                                                                    MySql重要知识梳理,在这里插入图片描述,第50张

                                                                                    InnoDB的行锁是针对索引加的锁,不是针对记录加的锁 ,并且该索引不能失效,否则会从行锁升级为表锁 。

                                                                                    SQL优化总结

                                                                                    MySql重要知识梳理,在这里插入图片描述,第51张

                                                                                    三.锁

                                                                                    锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU、

                                                                                    RAM、I/O)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有

                                                                                    效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个

                                                                                    角度来说,锁对数据库而言显得尤其重要,也更加复杂。

                                                                                    MySQL中的锁,按照锁的粒度分,分为以下三类:

                                                                                    • 全局锁:锁定数据库中的所有表。
                                                                                    • 表级锁:每次操作锁住整张表。
                                                                                    • 行级锁:每次操作锁住对应的行数据。

                                                                                      1.全局锁

                                                                                      全局锁就是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML的写语句,DDL语句,已经更新操作的事务提交语句都将被阻塞。

                                                                                      其典型的使用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。

                                                                                      全局锁加锁之后的情景

                                                                                      MySql重要知识梳理,在这里插入图片描述,第52张

                                                                                      对数据库进行进行逻辑备份之前,先对整个数据库加上全局锁,一旦加了全局锁之后,其他的DDL、DML全部都处于阻塞状态,但是可以执行DQL语句,也就是处于只读状态,而数据备份就是查询操作。

                                                                                      那么数据在进行逻辑备份的过程中,数据库中的数据就是不会发生变化的,这样就保证了数据的一致性和完整性。

                                                                                      1.语法

                                                                                      1). 加全局锁

                                                                                      flush tables with read lock ;
                                                                                      

                                                                                      2). 数据备份

                                                                                      mysqldump -uroot –pxxx 数据库> 导出的数据库名.sql
                                                                                      

                                                                                      3). 释放锁

                                                                                      unlock tables ;
                                                                                      

                                                                                      2.特点

                                                                                      数据库中加全局锁,是一个比较重的操作,存在以下问题:

                                                                                      • 如果在主库上备份,那么在备份期间都不能执行更新,业务基本上就得停摆。
                                                                                      • 如果在从库上备份,那么在备份期间从库不能执行主库同步过来的二进制日志(binlog),会导致主从延迟。

                                                                                        在InnoDB引擎中,我们可以在备份时加上参数 --single-transaction 参数来完成不加锁的一致性数据备份。

                                                                                        mysqldump --single-transaction -uroot –pxxx 数据库 > 导出的数据库名.sql
                                                                                        

                                                                                        2.表级锁

                                                                                        介绍

                                                                                        表级锁,每次操作锁住整张表。锁定粒度大,发生锁冲突的概率最高,并发度最低。应用在MyISAM、InnoDB、BDB等存储引擎中。

                                                                                        对于表级锁,主要分为以下三类:

                                                                                        • 表锁
                                                                                        • 元数据锁(meta data lock,MDL)
                                                                                        • 意向锁

                                                                                          1.表锁

                                                                                          对于表锁,分为两类:

                                                                                          • 表共享读锁(read lock)
                                                                                          • 表独占写锁(write lock)

                                                                                            语法:

                                                                                            加锁:lock tables 表名… read/write。

                                                                                            释放锁:unlock tables / 客户端断开连接 。

                                                                                            MySql重要知识梳理,在这里插入图片描述,第53张

                                                                                            左侧为客户端一,对指定表加了写锁,会阻塞右侧客户端的读和写。

                                                                                            MySql重要知识梳理,在这里插入图片描述,第54张

                                                                                            左侧为客户端一,对指定表加了读锁,不会影响右侧客户端二的读,但是会阻塞右侧客户端的写。

                                                                                            MySql重要知识梳理,在这里插入图片描述,第55张

                                                                                            结论: 读锁不会阻塞其他客户端的读,但是会阻塞写。写锁既会阻塞其他客户端的读,又会阻塞其他客户端的写。

                                                                                            MySql重要知识梳理,在这里插入图片描述,第56张

                                                                                            释放锁另一个客户端可以成功写入成功

                                                                                            2.元数据锁

                                                                                            meta data lock , 元数据锁,简写MDL。

                                                                                            MDL加锁过程是系统自动控制,无需显式使用,在访问一张表的时候会自动加上。MDL锁主要作用是维护表元数据的数据一致性,在表上有活动事务的时候,不可以对元数据进行写入操作。为了避免DML与DDL冲突,保证读写的正确性。

                                                                                            这里的元数据,大家可以简单理解为就是一张表的表结构。 也就是说,某一张表涉及到未提交的事务时,是不能够修改这张表的表结构的。

                                                                                            在MySQL5.5中引入了MDL,当对一张表进行增删改查的时候,加MDL读锁(共享);当对表结构进行变更操作的时候,加MDL写锁(排他)。

                                                                                            常见的SQL操作时,所添加的元数据锁:

                                                                                            MySql重要知识梳理,在这里插入图片描述,第57张

                                                                                            查看元数据锁

                                                                                            select object_type,object_schema,object_name,lock_type,lock_duration from
                                                                                            performance_schema.metadata_locks ;
                                                                                            

                                                                                            MySql重要知识梳理,在这里插入图片描述,第58张

                                                                                            当开启事务的时候执行查询和修改查看元数据锁发现共享读锁和共享写锁全部开启了。

                                                                                            3.意向锁

                                                                                            1). 介绍

                                                                                            为了避免DML在执行时,加的行锁与表锁的冲突,在InnoDB中引入了意向锁,使得表锁不用检查每行数据是否加锁,使用意向锁来减少表锁的检查。

                                                                                            MySql重要知识梳理,在这里插入图片描述,第59张

                                                                                            MySql重要知识梳理,在这里插入图片描述,第60张

                                                                                            MySql重要知识梳理,在这里插入图片描述,第61张

                                                                                            • 意向共享锁(IS): 由语句select … lock in share mode添加 。 与 表锁共享锁

                                                                                              (read)兼容,与表锁排他锁(write)互斥。

                                                                                            • 意向排他锁(IX): 由insert、update、delete、select…for update添加 。

                                                                                              与表锁共享锁(read)及排他锁(write)都互斥,意向锁之间不会互斥。

                                                                                              一旦事务提交了,意向共享锁、意向排他锁,都会自动释放。

                                                                                              可以通过以下SQL,查看意向锁及行锁的加锁情况:

                                                                                              select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from

                                                                                              performance_schema.data_locks;


                                                                                              下面演示意向共享锁(IS)的加锁情况

                                                                                              左侧客户端开启事务加入意向共享锁(IS),右侧可以加入表共享读锁,但是添加表共享写锁失败

                                                                                              MySql重要知识梳理,在这里插入图片描述,第62张


                                                                                              下面演示意向排他锁(IX)的加锁情况

                                                                                              左侧客户端开启事务加入意向排他锁(IX),右侧不可以加入表共享读锁和写锁。

                                                                                              MySql重要知识梳理,在这里插入图片描述,第63张

                                                                                              3.行级锁

                                                                                              介绍

                                                                                              行级锁,每次操作锁住对应的行数据。锁定粒度最小,发生锁冲突的概率最低,并发度最高。应用在InnoDB存储引擎中。

                                                                                              InnoDB的数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁。对于行级锁,主要分为以下三类:

                                                                                              • 行锁(Record Lock):锁定单个行记录的锁,防止其他事务对此行进行update和delete。在RC、RR隔离级别下都支持。

                                                                                                MySql重要知识梳理,在这里插入图片描述,第64张

                                                                                              • 间隙锁(Gap Lock):锁定索引记录间隙(不含该记录),确保索引记录间隙不变,防止其他事务在这个间隙进行insert,产生幻读。在RR隔离级别下都支持。

                                                                                                MySql重要知识梳理,在这里插入图片描述,第65张

                                                                                                • 临键锁(Next-Key Lock):行锁和间隙锁组合,同时锁住数据,并锁住数据前面的间隙Gap。在RR隔离级别下支持。

                                                                                                  MySql重要知识梳理,在这里插入图片描述,第66张

                                                                                                  1.行锁

                                                                                                  InnoDB实现了以下两种类型的行锁:

                                                                                                  • 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排它锁。
                                                                                                  • 排他锁(X):允许获取排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁。

                                                                                                    MySql重要知识梳理,在这里插入图片描述,第67张

                                                                                                    MySql重要知识梳理,在这里插入图片描述,第68张

                                                                                                    数据演示

                                                                                                    默认情况下,InnoDB在 REPEATABLE READ事务隔离级别运行,InnoDB使用 next-key 锁进行搜索和索引扫描,以防止幻读。

                                                                                                    • 针对唯一索引进行检索时,对已存在的记录进行等值匹配时,将会自动优化为行锁。
                                                                                                    • InnoDB的行锁是针对于索引加的锁,不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,此时 就会升级为表锁

                                                                                                      可以通过以下SQL,查看意向锁及行锁的加锁情况:

                                                                                                      select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from
                                                                                                      performance_schema.data_locks;
                                                                                                      

                                                                                                      数据准备

                                                                                                      CREATE TABLE `stu` (
                                                                                                      `id` int NOT NULL PRIMARY KEY AUTO_INCREMENT,
                                                                                                      `name` varchar(255) DEFAULT NULL,
                                                                                                      `age` int NOT NULL
                                                                                                      ) ENGINE = InnoDB CHARACTER SET = utf8mb4;
                                                                                                      INSERT INTO `stu` VALUES (1, 'tom', 1);
                                                                                                      INSERT INTO `stu` VALUES (3, 'cat', 3);
                                                                                                      INSERT INTO `stu` VALUES (8, 'rose', 8);
                                                                                                      INSERT INTO `stu` VALUES (11, 'jetty', 11);
                                                                                                      INSERT INTO `stu` VALUES (19, 'lily', 19);
                                                                                                      INSERT INTO `stu` VALUES (25, 'luci', 25);
                                                                                                      

                                                                                                      1.普通的select语句,执行时,不会加锁。

                                                                                                      MySql重要知识梳理,在这里插入图片描述,第69张

                                                                                                      2.select…lock in share mode,加共享锁,共享锁与共享锁之间兼容。

                                                                                                      MySql重要知识梳理,在这里插入图片描述,第70张

                                                                                                      3.共享锁与排他锁之间互斥。

                                                                                                      MySql重要知识梳理,在这里插入图片描述,第71张

                                                                                                      客户端一获取的是id为1这行的共享锁,客户端二是可以获取id为3这行的排它锁的,因为不是同一行数据。 而如果客户端二想获取id为1这行的排他锁,会处于阻塞状态,以为共享锁与排他锁之间互斥。


                                                                                                      4.排它锁与排他锁之间互斥

                                                                                                      MySql重要知识梳理,在这里插入图片描述,第72张

                                                                                                      当客户端一,执行update语句,会为id为1的记录加排他锁; 客户端二,如果也执行update语句更

                                                                                                      新id为1的数据,也要为id为1的数据加排他锁,但是客户端二会处于阻塞状态,因为排他锁之间是互

                                                                                                      斥的。 直到客户端一,把事务提交了,才会把这一行的行锁释放,此时客户端二,解除阻塞。

                                                                                                      5.无索引行锁升级为表锁(不演示上面有例子)

                                                                                                      2.间隙锁&临键锁

                                                                                                      默认情况下,InnoDB在 REPEATABLE READ事务隔离级别运行,InnoDB使用 next-key 锁进行搜

                                                                                                      索和索引扫描,以防止幻读

                                                                                                      • 索引上的等值查询(唯一索引),给不存在的记录加锁时, 优化为间隙锁 。
                                                                                                      • 索引上的等值查询(非唯一普通索引),向右遍历时最后一个值不满足查询需求时,next-key

                                                                                                        lock 退化为间隙锁。

                                                                                                      • 索引上的范围查询(唯一索引)–会访问到不满足条件的第一个值为止。

                                                                                                        注意:间隙锁唯一目的是防止其他事务插入间隙。间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事务在同一间隙上采用间隙锁。

                                                                                                        数据演示
                                                                                                        1. 索引上的等值查询(唯一索引),给不存在的记录加锁时, 优化为间隙锁 。

                                                                                                        MySql重要知识梳理,在这里插入图片描述,第73张

                                                                                                        2. 索引上的等值查询(非唯一普通索引),向右遍历时最后一个值不满足查询需求时,next-key lock 退化为间隙锁。

                                                                                                        介绍分析一下:

                                                                                                        我们知道InnoDB的B+树索引,叶子节点是有序的双向链表。 假如,我们要根据这个二级索引查询值为18的数据,并加上共享锁,我们是只锁定18这一行就可以了吗? 并不是,因为是非唯一索引,这个结构中可能有多个18的存在,所以,在加锁时会继续往后找,找到一个不满足条件的值(当前案例中也就是29)。此时会对18加临键锁,并对29之前的间隙加锁。

                                                                                                        MySql重要知识梳理,在这里插入图片描述,第74张

                                                                                                        MySql重要知识梳理,在这里插入图片描述,第75张

                                                                                                        3.索引上的范围查询(唯一索引)–会访问到不满足条件的第一个值为止。

                                                                                                        MySql重要知识梳理,在这里插入图片描述,第76张

                                                                                                        查询的条件为id>=19,并添加共享锁。 此时我们可以根据数据库表中现有的数据,将数据分为三个部

                                                                                                        分:

                                                                                                        [19]

                                                                                                        (19,25]

                                                                                                        (25,+∞]

                                                                                                        所以数据库数据在加锁是,就是将19加了行锁,25的临键锁(包含25及25之前的间隙),正无穷的临键锁(正无穷及之前的间隙)。


                                                                                                        总结

                                                                                                        MySql重要知识梳理,请添加图片描述,第77张

                                                                                                        四.InnoDB引擎

                                                                                                        1.概述

                                                                                                        InnoDB的逻辑存储结构如下图所示:

                                                                                                        MySql重要知识梳理,在这里插入图片描述,第78张

                                                                                                        1). 表空间

                                                                                                        表空间是InnoDB存储引擎逻辑结构的最高层, 如果用户启用了参数 innodb_file_per_table(在8.0版本中默认开启) ,则每张表都会有一个表空间(xxx.ibd),一个mysql实例可以对应多个表空间,用于存储记录、索引等数据。

                                                                                                        2). 段

                                                                                                        段,分为数据段(Leaf node segment)、索引段(Non-leaf node segment)、回滚段(Rollback segment),InnoDB是索引组织表,数据段就是B+树的叶子节点, 索引段即为B+树的非叶子节点。段用来管理多个Extent(区)。

                                                                                                        3). 区

                                                                                                        区,表空间的单元结构,每个区的大小为1M。 默认情况下, InnoDB存储引擎页大小为16K, 即一个区中一共有64个连续的页。

                                                                                                        4). 页

                                                                                                        页,是InnoDB 存储引擎磁盘管理的最小单元,每个页的大小默认为 16KB。为了保证页的连续性,InnoDB 存储引擎每次从磁盘申请 4-5 个区。

                                                                                                        5). 行

                                                                                                        行,InnoDB 存储引擎数据是按行进行存放的。

                                                                                                        在行中,默认有两个隐藏字段:

                                                                                                        • Trx_id:每次对某条记录进行改动时,都会把对应的事务id赋值给trx_id隐藏列。
                                                                                                        • Roll_pointer:每次对某条引记录进行改动时,都会把旧的版本写入到undo日志中,然后这个隐藏列就相当于一个指针,可以通过它来找到该记录修改前的信息。

                                                                                                          2.MySQL的架构图

                                                                                                          MySQL5.5 版本开始,默认使用InnoDB存储引擎,它擅长事务处理,具有崩溃恢复特性,在日常开发

                                                                                                          中使用非常广泛。下面是InnoDB架构图,左侧为内存结构,右侧为磁盘结构。

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第79张

                                                                                                          1.内存结构

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第80张

                                                                                                          1). Buffer Pool

                                                                                                          InnoDB存储引擎基于磁盘文件存储,访问物理硬盘和在内存中进行访问,速度相差很大,为了尽可能

                                                                                                          弥补这两者之间的I/O效率的差值,就需要把经常使用的数据加载到缓冲池中,避免每次访问都进行磁

                                                                                                          盘I/O。在InnoDB的缓冲池中不仅缓存了索引页和数据页,还包含了undo页、插入缓存、自适应哈希索引以及InnoDB的锁信息等等。缓冲池 Buffer Pool,是主内存中的一个区域,里面可以缓存磁盘上经常操作的真实数据,在执行增删改查操作时,先操作缓冲池中的数据(若缓冲池没有数据,则从磁盘加载并缓存),然后再以一定频率刷新到磁盘,从而减少磁盘IO,加快处理速度。

                                                                                                          缓冲池以Page页为单位,底层采用链表数据结构管理Page。根据状态,将Page分为三种类型:

                                                                                                          • free page:空闲page,未被使用。

                                                                                                          • clean page:被使用page,数据没有被修改过。

                                                                                                          • dirty page:脏页,被使用page,数据被修改过,也中数据与磁盘的数据产生了不一致。

                                                                                                          2). Change Buffer

                                                                                                          Change Buffer,更改缓冲区(针对于非唯一二级索引页),在执行DML语句时,如果这些数据Page

                                                                                                          没有在Buffer Pool中,不会直接操作磁盘,而会将数据变更存在更改缓冲区 Change Buffer

                                                                                                          中,在未来数据被读取时,再将数据合并恢复到Buffer Pool中,再将合并后的数据刷新到磁盘中。

                                                                                                          Change Buffer的意义是什么呢?

                                                                                                          先来看一幅图,这个是二级索引的结构图:

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第81张

                                                                                                          与聚集索引不同,二级索引通常是非唯一的,并且以相对随机的顺序插入二级索引。同样,删除和更新可能会影响索引树中不相邻的二级索引页,如果每一次都操作磁盘,会造成大量的磁盘IO。有了

                                                                                                          ChangeBuffer之后,我们可以在缓冲池中进行合并处理,减少磁盘IO。

                                                                                                          3). Adaptive Hash Index

                                                                                                          自适应hash索引,用于优化对Buffer Pool数据的查询。MySQL的innoDB引擎中虽然没有直接支持

                                                                                                          hash索引,但是给我们提供了一个功能就是这个自适应hash索引。因为前面我们讲到过,hash索引在进行等值匹配时,一般性能是要高于B+树的,因为hash索引一般只需要一次IO即可,而B+树,可能需要几次匹配,所以hash索引的效率要高,但是hash索引又不适合做范围查询、模糊匹配等。

                                                                                                          InnoDB存储引擎会监控对表上各索引页的查询,如果观察到在特定的条件下hash索引可以提升速度,则建立hash索引,称之为自适应hash索引。

                                                                                                          自适应哈希索引,无需人工干预,是系统根据情况自动完成。

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第82张

                                                                                                          4). Log Buffer

                                                                                                          Log Buffer:日志缓冲区,用来保存要写入到磁盘中的log日志数据(redo log 、undo log),

                                                                                                          默认大小为 16MB,日志缓冲区的日志会定期刷新到磁盘中。如果需要更新、插入或删除许多行的事

                                                                                                          务,增加日志缓冲区的大小可以节省磁盘 I/O。

                                                                                                          参数:

                                                                                                          innodb_log_buffer_size:缓冲区大小

                                                                                                          innodb_flush_log_at_trx_commit:日志刷新到磁盘时机,取值主要包含以下三个:

                                                                                                          1: 日志在每次事务提交时写入并刷新到磁盘,默认值。

                                                                                                          0: 每秒将日志写入并刷新到磁盘一次。

                                                                                                          2: 日志在每次事务提交后写入,并每秒刷新到磁盘一次。

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第83张

                                                                                                          2.磁盘结构

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第84张

                                                                                                          1). System Tablespace

                                                                                                          系统表空间是更改缓冲区的存储区域。如果表是在系统表空间而不是每个表文件或通用表空间中创建

                                                                                                          的,它也可能包含表和索引数据。(在MySQL5.x版本中还包含InnoDB数据字典、undolog等)

                                                                                                          参数:innodb_data_file_path

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第85张

                                                                                                          系统表空间,默认的文件名叫 ibdata1。

                                                                                                          2). File-Per-Table Tablespaces

                                                                                                          如果开启了innodb_file_per_table开关 ,则每个表的文件表空间包含单个InnoDB表的数据和索

                                                                                                          引 ,并存储在文件系统上的单个数据文件中。

                                                                                                          开关参数:innodb_file_per_table ,该参数默认开启。

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第86张

                                                                                                          那也就是说,我们没创建一个表,都会产生一个表空间文件,如图:

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第87张

                                                                                                          3). General Tablespaces

                                                                                                          通用表空间,需要通过 CREATE TABLESPACE 语法创建通用表空间,在创建表时,可以指定该表空

                                                                                                          间。

                                                                                                          A. 创建表空间

                                                                                                          CREATE TABLESPACE ts_name ADD DATAFILE 'file_name' ENGINE = engine_name;
                                                                                                          

                                                                                                          ts_name:表空间的名字

                                                                                                          DATAFILE :数据文件的名字,以ibd结尾

                                                                                                          ENGINE:存储引擎

                                                                                                          eg:

                                                                                                          CREATE TABLESPACE tablespaceTest ADD DATAFILE 'spaceTest.ibd' ENGINE = innodb;
                                                                                                          

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第88张

                                                                                                          B. 创建表时指定表空间

                                                                                                          CREATE TABLE xxx ... TABLESPACE ts_name;
                                                                                                          

                                                                                                          4). Undo Tablespaces

                                                                                                          撤销表空间,MySQL实例在初始化时会自动创建两个默认的undo表空间(初始大小16M),用于存储undo log日志。

                                                                                                          5). Temporary Tablespaces

                                                                                                          InnoDB 使用会话临时表空间和全局临时表空间。存储用户创建的临时表等数据。

                                                                                                          6). Doublewrite Buffer Files

                                                                                                          双写缓冲区,innoDB引擎将数据页从Buffer Pool刷新到磁盘前,先将数据页写入双写缓冲区文件

                                                                                                          中,便于系统异常时恢复数据。

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第89张

                                                                                                          7). Redo Log

                                                                                                          重做日志,是用来实现事务的持久性。 该日志文件由两部分组成:重做日志缓冲(redo log

                                                                                                          buffer)以及重做日志文件(redo log),前者是在内存中,后者在磁盘中。当事务提交之后会把所

                                                                                                          有修改信息都会存到该日志中, 用于在刷新脏页到磁盘时,发生错误时, 进行数据恢复使用。

                                                                                                          以循环方式写入重做日志文件,涉及两个文件:

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第90张


                                                                                                          MySql重要知识梳理,在这里插入图片描述,第91张

                                                                                                          3.后台线程

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第92张

                                                                                                          在InnoDB的后台线程中,分为4类,分别是:Master Thread 、IO Thread、Purge Thread、

                                                                                                          Page Cleaner Thread。

                                                                                                          1). Master Thread

                                                                                                          核心后台线程,负责调度其他线程,还负责将缓冲池中的数据异步刷新到磁盘中, 保持数据的一致性,还包括脏页的刷新、合并插入缓存、undo页的回收 。

                                                                                                          2). IO Thread

                                                                                                          在InnoDB存储引擎中大量使用了AIO来处理IO请求, 这样可以极大地提高数据库的性能,而IO

                                                                                                          Thread主要负责这些IO请求的回调。

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第93张

                                                                                                           show engine innodb status \G;
                                                                                                          

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第94张

                                                                                                          3). Purge Thread

                                                                                                          主要用于回收事务已经提交了的undo log,在事务提交之后,undo log可能不用了,就用它来回

                                                                                                          收。

                                                                                                          4). Page Cleaner Thread

                                                                                                          协助 Master Thread 刷新脏页到磁盘的线程,它可以减轻 Master Thread 的工作压力,减少阻

                                                                                                          塞。

                                                                                                          五.事务原理

                                                                                                          1.事务基础

                                                                                                          1). 事务

                                                                                                          事务 是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系

                                                                                                          统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。

                                                                                                          2). 特性

                                                                                                          • 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。

                                                                                                          • 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。

                                                                                                          • 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环

                                                                                                          境下运行。

                                                                                                          • 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。

                                                                                                          那实际上,我们研究事务的原理,就是研究MySQL的InnoDB引擎是如何保证事务的这四大特性的。

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第95张

                                                                                                          而对于这四大特性,实际上分为两个部分。 其中的原子性、一致性、持久性,实际上是由InnoDB中的两份日志来保证的,一份是redo log日志,一份是undo log日志。 而隔离性是通过数据库的锁,

                                                                                                          加上MVCC来保证的。

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第96张

                                                                                                          我们在讲解事务原理的时候,主要就是来研究一下redolog,undolog以及MVCC。

                                                                                                          2.redo log

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第97张

                                                                                                          重做日志,记录的是事务提交时数据页的物理修改,是用来实现事务的持久性。

                                                                                                          该日志文件由两部分组成:**重做日志缓冲(redo log buffer)以及重做日志文件(redo log

                                                                                                          file),前者是在内存中,后者在磁盘中。**当事务提交之后会把所有修改信息都存到该日志文件中, 用

                                                                                                          于在刷新脏页到磁盘,发生错误时, 进行数据恢复使用。

                                                                                                          如果没有redolog,可能会存在什么问题的? 我们一起来分析一下

                                                                                                          我们知道,在InnoDB引擎中的内存结构中,主要的内存区域就是缓冲池,在缓冲池中缓存了很多的数

                                                                                                          据页。 当我们在一个事务中,执行多个增删改的操作时,InnoDB引擎会先操作缓冲池中的数据,如果缓冲区没有对应的数据,会通过后台线程将磁盘中的数据加载出来,存放在缓冲区中,然后将缓冲池中的数据修改,修改后的数据页我们称为脏页。 而脏页则会在一定的时机,通过后台线程刷新到磁盘中,从而保证缓冲区与磁盘的数据一致。 而缓冲区的脏页数据并不是实时刷新的,而是一段时间之后将缓冲区的数据刷新到磁盘中,假如刷新到磁盘的过程出错了,而提示给用户事务提交成功,而数据却没有持久化下来,这就出现问题了,没有保证事务的持久性。

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第98张

                                                                                                          那么,如何解决上述的问题呢? 在InnoDB中提供了一份日志 redo log,接下来我们再来分析一

                                                                                                          下,通过redolog如何解决这个问题。

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第99张

                                                                                                          有了redolog之后,当对缓冲区的数据进行增删改之后,会首先将操作的数据页的变化,记录在redo

                                                                                                          log buffer中。在事务提交时,会将redo log buffer中的数据刷新到redo log磁盘文件中。

                                                                                                          过一段时间之后,如果刷新缓冲区的脏页到磁盘时,发生错误,此时就可以借助于redo log进行数据

                                                                                                          恢复,这样就保证了事务的持久性。 而如果脏页成功刷新到磁盘 或 或者涉及到的数据已经落盘,此

                                                                                                          时redolog就没有作用了,就可以删除了,所以存在的两个redolog文件是循环写的。

                                                                                                          那为什么每一次提交事务,要刷新redo log 到磁盘中呢,而不是直接将buffer pool中的脏页刷新

                                                                                                          到磁盘呢 ?

                                                                                                          因为在业务操作中,我们操作数据一般都是随机读写磁盘的,而不是顺序读写磁盘。 而redo log在

                                                                                                          往磁盘文件中写入数据,由于是日志文件,所以都是顺序写的。顺序写的效率,要远大于随机写。 这

                                                                                                          种先写日志的方式,称之为 WAL(Write-Ahead Logging)。

                                                                                                          2.undo log

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第100张

                                                                                                          回滚日志,用于记录数据被修改前的信息 , 作用包含两个 : 提供回滚(保证事务的原子性) 和

                                                                                                          MVCC(多版本并发控制) 。

                                                                                                          undo log和redo log记录物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo

                                                                                                          log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的

                                                                                                          update记录。当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。

                                                                                                          Undo log销毁:undo log在事务执行时产生,事务提交时,并不会立即删除undo log,因为这些

                                                                                                          日志可能还用于MVCC。

                                                                                                          Undo log存储:undo log采用段的方式进行管理和记录,存放在前面介绍的 rollback segment

                                                                                                          回滚段中,内部包含1024个undo log segment。

                                                                                                          3.MVCC

                                                                                                          1). 当前读

                                                                                                          读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加

                                                                                                          锁。对于我们日常的操作,如:select … lock in share mode(共享锁),select …

                                                                                                          for update、update、insert、delete(排他锁)都是一种当前读。

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第101张

                                                                                                          在测试中我们可以看到,即使是在默认的RR隔离级别下,事务A中依然可以读取到事务B最新提交的内容,因为在查询语句后面加上了 lock in share mode 共享锁,此时是当前读操作。当然,当我们

                                                                                                          加排他锁的时候,也是当前读操作。

                                                                                                          2). 快照读

                                                                                                          简单的select(不加锁)就是快照读,快照读,读取的是记录数据的可见版本,有可能是历史数据,

                                                                                                          不加锁,是非阻塞读。

                                                                                                          • Read Committed:每次select,都生成一个快照读。

                                                                                                          • Repeatable Read:开启事务后第一个select语句才是快照读的地方。

                                                                                                          • Serializable:快照读会退化为当前读。

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第102张

                                                                                                          在测试中,我们看到即使事务B提交了数据,事务A中也查询不到。 原因就是因为普通的select是快照

                                                                                                          读,而在当前默认的RR隔离级别下,开启事务后第一个select语句才是快照读的地方,后面执行相同

                                                                                                          的select语句都是从快照中获取数据,可能不是当前的最新数据,这样也就保证了可重复读。、

                                                                                                          3). MVCC

                                                                                                          全称 Multi-Version Concurrency Control,多版本并发控制。指维护一个数据的多个版本,

                                                                                                          使得读写操作没有冲突,快照读为MySQL实现MVCC提供了一个非阻塞读功能。MVCC的具体实现,还需要依赖于数据库记录中的三个隐式字段、undo log日志、readView。

                                                                                                          1.隐藏字段

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第103张

                                                                                                          而上述的前两个字段是肯定会添加的, 是否添加最后一个字段DB_ROW_ID,得看当前表有没有主键,如果有主键,则不会添加该隐藏字段。

                                                                                                          数据演示

                                                                                                          1). 查看有主键的表 stu

                                                                                                          进入服务器中的 /var/lib/mysql/或则windows系统中的data目录, 查看stu的表结构信息, 通过如下指令:

                                                                                                          ibd2sdi stu.ibd
                                                                                                          

                                                                                                          上面是linux里面的命令

                                                                                                          ibd2sdi.exe "C:\ProgramData\MySQL\MySQL Server 8.0\Data\ts\stu.ibd"
                                                                                                          

                                                                                                          上面是windows里面的命令需要先找到ibd2sdi.exe的目录位置

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第104张

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第105张

                                                                                                          查看到的表结构信息中,有一栏 columns,在其中我们会看到处理我们建表时指定的字段以外,还有

                                                                                                          额外的两个字段 分别是:DB_TRX_ID 、 DB_ROLL_PTR ,因为该表有主键,所以没有DB_ROW_ID隐藏字段。

                                                                                                          2). 查看没有主键的表 employee

                                                                                                          查看到的表结构信息中,有一栏 columns,在其中我们会看到处理我们建表时指定的字段以外,还有

                                                                                                          额外的三个字段 分别是:DB_TRX_ID 、 DB_ROLL_PTR 、DB_ROW_ID,因为employee表是没有指定主键的。

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第106张

                                                                                                          查看到的表结构信息中,有一栏 columns,在其中我们会看到处理我们建表时指定的字段以外,还有

                                                                                                          额外的三个字段 分别是:DB_TRX_ID 、 DB_ROLL_PTR 、DB_ROW_ID,因为employee表是没有

                                                                                                          指定主键的。

                                                                                                          2.undolog版本链

                                                                                                          1.介绍

                                                                                                          回滚日志,在insert、update、delete的时候产生的便于数据回滚的日志。

                                                                                                          当insert的时候,产生的undo log日志只在回滚时需要,在事务提交后,可被立即删除。

                                                                                                          而update、delete的时候,产生的undo log日志不仅在回滚时需要,在快照读时也需要,不会立即

                                                                                                          被删除。

                                                                                                          2.版本链

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第107张

                                                                                                          DB_TRX_ID : 代表最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID,是
                                                                                                          自增的。
                                                                                                          DB_ROLL_PTR : 由于这条数据是才插入的,没有被更新过,所以该字段值为null。
                                                                                                          

                                                                                                          然后,有四个并发事务同时在访问这张表。

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第108张

                                                                                                          当事务2执行第一条修改语句时,会记录undo log日志,记录数据变更之前的样子; 然后更新记录,

                                                                                                          并且记录本次操作的事务ID,回滚指针,回滚指针用来指定如果发生回滚,回滚到哪一个版本。

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第109张

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第110张

                                                                                                          当事务3执行第一条修改语句时,也会记录undo log日志,记录数据变更之前的样子; 然后更新记

                                                                                                          录,并且记录本次操作的事务ID,回滚指针,回滚指针用来指定如果发生回滚,回滚到哪一个版本。

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第111张

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第112张

                                                                                                          当事务4执行第一条修改语句时,也会记录undo log日志,记录数据变更之前的样子; 然后更新记

                                                                                                          录,并且记录本次操作的事务ID,回滚指针,回滚指针用来指定如果发生回滚,回滚到哪一个版本。

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第113张

                                                                                                          最终我们发现,不同事务或相同事务对同一条记录进行修改,会导致该记录的undolog生成一条记录版本链表,链表的头部是最新的旧记录,链表尾部是最早的旧记录。

                                                                                                          3.readview

                                                                                                          ReadView(读视图)是 快照读 SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务

                                                                                                          (未提交的)id。

                                                                                                          ReadView中包含了四个核心字段:

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第114张

                                                                                                          而在readview中就规定了版本链数据的访问规则:

                                                                                                          trx_id 代表当前undolog版本链对应事务ID。

                                                                                                          MySql重要知识梳理,在这里插入图片描述,第115张

                                                                                                          不同的隔离级别,生成ReadView的时机不同:

                                                                                                          • READ COMMITTED :在事务中每一次执行快照读时生成ReadView。
                                                                                                          • REPEATABLE READ:仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。
                                                                                                            4.原理分析
                                                                                                            1.RC隔离级别

                                                                                                            RC隔离级别下,在事务中每一次执行快照读时生成ReadView。

                                                                                                            我们就来分析事务5中,两次快照读读取数据,是如何获取数据的?

                                                                                                            在事务5中,查询了两次id为30的记录,由于隔离级别为Read Committed,所以每一次进行快照读

                                                                                                            都会生成一个ReadView,那么两次生成的ReadView如下。

                                                                                                            MySql重要知识梳理,在这里插入图片描述,第116张

                                                                                                            那么这两次快照读在获取数据时,就需要根据所生成的ReadView以及ReadView的版本链访问规则,

                                                                                                            到undolog版本链中匹配数据,最终决定此次快照读返回的数据。

                                                                                                            MySql重要知识梳理,在这里插入图片描述,第117张

                                                                                                            MySql重要知识梳理,在这里插入图片描述,第118张

                                                                                                            2.RR隔离级别

                                                                                                            RR隔离级别下,仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。 而RR 是可重复读,在一个事务中,执行两次相同的select语句,查询到的结果是一样的。

                                                                                                            那MySQL是如何做到可重复读的呢?

                                                                                                            MySql重要知识梳理,在这里插入图片描述,第119张

                                                                                                            所以呢,MVCC的实现原理就是通过 InnoDB表的隐藏字段、UndoLog 版本链、ReadView来实现的。

                                                                                                            而MVCC + 锁,则实现了事务的隔离性。 而一致性则是由redolog 与 undolog保证。

                                                                                                            MySql重要知识梳理,在这里插入图片描述,第120张

                                                                                                            5.事务总结

                                                                                                            原子性: undo log。

                                                                                                            一致性: undo log、redo log。

                                                                                                            持久性: redo log。

                                                                                                            隔离性: MVCC+锁。


                                                                                                            undo log和 redo log的区别

                                                                                                            redo log记录的是数据页的物理变化,服务宕机可用来同步数据,而undo log不同,它主要记录的是逻辑日志,当事务回滚时,通过逆操作回复原来的数据,比如我们删除一条数据的时候,就会在undo log日志文件中新增一条delete语句,如果发生回滚就执行逆操作;

                                                                                                            redo log保证了事物的持久性,undo log保证了事物的原子性和一致性。


                                                                                                            事务中的隔离性如何保证的呢?

                                                                                                            锁:排他锁(如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁)

                                                                                                            mvcc:多版本并发控制。