MySQL

目录

一、概述

二、MySQL的常见存储引擎

三、InnoDB存储引擎 

        1、InnoDB磁盘结构

                (1)段

                (2)区

                (3)页

                (4)行

        2、InnoDB的内存结构(默认128MB)

                (1)Buffer Pool

                (2)Change Pool

                (3)Log Buffer

四、索引

        1、B+树索引结构

        2、索引分类

五、日志

        Bin-Log(server)逻辑日志:

        Redo-Log(存储引擎)物理日志:

        Undo-Log(存储引擎):

六、事务

        什么是事事务?

        事务特性(ACID):

        事务隔离级别:

七、MVCC(多版本并发控制)

        工作原理:

        ReadView:

八、锁

        行锁

        表锁


一、概述

        MySQL是一个关系型数据库管理系统(RDBMS),由瑞典的MySQL AB公司开发,目前属于Oracle旗下产品。MySQL以其开源、免费、体积小、速度快、总体拥有成本低等特点,成为全球最受欢迎的数据库管理系统之一,特别是在Web应用方面,MySQL是表现最优异的关系数据库管理系统应用软件之一。

二、MySQL的常见存储引擎

        MySQL的存储引擎非常多,比如InnoDBdunhao、MyISAM、Memory、Archive、CSV等,当然最常用的还是InnoDB和MyISAM,InnoDB是MySQL目前的存储默认存储引擎以下是他们两个主要的区别:

名称 MyISAMInnoDB
事务        不支持        支持
表锁        行锁
外键约束不支持支持
全文索引支持不支持
索引只支持主键索引支持主键索引和二级索引

       

    

 由于在日常开发中大家都默认使用InnoDB存储引擎,所以下面我们用InnoDB存储引擎展开 

三、InnoDB存储引擎 

        1、InnoDB磁盘结构

                (1)段

                段是一个逻辑存储结构,也就是说不是一块固定的空间,当然段是由下面的区组成,一个段中包含多个区,段存在多种分类:

                        数据段(Leaf node segment):用于存储B+树的叶子节点,即实际的数据记录。

                        索引段(Non-leaf node segment):用于存储B+树的非叶子节点,即索引信息。

                        回滚段(Rollback segment):用于存储回滚日志(Undo log),支持事务的回滚操作和多版本并发控制(MVCC)。

                (2)区

                区是一段连续的磁盘空间,由下面的页组成,一个区由64个连续的页(16KB)组成,区是存储数据的最小单元,也就是说MySQL写数据,一次从磁盘至少申请一个区的资源(1MB),为什么这样是因为,磁盘IO大家都知道很慢,但磁盘IO由两种,顺序写和随机写,顺序写就是在一块连续的磁盘空间上写,随机写则是随机在磁盘找位置写,顺序写的效率要高的多,索引MySQL采用这种方式去减少磁盘IO.

                (3)页

                页是数据库存储的核心单位,是内存和磁盘交互的基本单位,一个页的大小默认是16KB,不存数据的情况下也会占用空间,页有以下常见页:

                        用于存储B+树节点的页,包括叶子节点和非叶子节点。叶子节点中存放的是实际的数据记录,非叶子节点存放的是目录项(索引)。

                        Undo页(Undo Log Page):用于存储Undo日志的页,Undo日志用于支持事务的回滚操作。

                        系统页(System Page):用于存储系统信息的页,如表空间头信息等。

                        事务数据页(Transaction System Page):与事务处理相关的页,存储事务的元数据信息。

                页的内部结构:

              

                File Header:这个结构是每个页都会有的数据结构,其中存放了与其他页相连的指针(双指针)和表的元数据

                Page Header:这个结构不是所以页都会有,只有数据页会有,当我们存在溢出页时溢出页就不会存在此结构,此结构中存的是页内的元数据

                Infimum/supermum:这个结构可以看作是两条行信息,其中Infimum中会有指针指向这一页的第一行数据,supermum则会有页中数据的最后一行指向supermum信息

                User Records:存储的用户数据

                Free Space:尚未被用户记录使用的空间

                Page Directory:这个结构则会将数据划分为若干个模块,以优化查找效率

                File Tailer:里面主要是一些校验信息,用于保证数据的完整性

                页中的操作:

                数据访问:在数据页中,记录会按照主键值从小到大的顺序组成单向链表。为了提高查询效率,InnoDB还会为这些记录生成一个页目录,通过二分法快速定位到对应的槽,再遍历槽中的记录找到指定数据。

                数据的插入和删除:随着数据的插入和删除,页可能会变得过满或过空。为了保持数据页的均衡和提高查询效率,InnoDB会执行页分裂或页合并操作。

                (4)行

                行的类型非常多,我们这里以Compact为例,在我们存储数据时,数据其实是存储在行中,也就是说,行是数据存储的最小单位,这些行由页进行管理,一个行的大小最大为700byte,当一行的数据量大于这个数值后,则会创建溢出页,在行内则会保存一个指针指向溢出页,也正是因为行,mysql才能实现MVCC(多版本并发控制)和高并发的特点,由于其需要支持事务等特性,所以结构也是最复杂的:

                其中变长字段长度列表记录的是每个字段的偏移量

                NULL列表:表示数据为null的列

                记录头中的信息非常重要,也是实现各种机制的根本,最重要的有:delete_mask,删除标记,当我们删除一个一行信息时,Innodb不会立即删除这行,而是改变改标记,因为存在事务等特性,万一需要回滚等操作只需要该变即可;next_record,指针,指向下一行的偏移量,每一行的数据也是因为这个属性连接成一个链表的形式,这页中的最后一行数据的改字段会指向supermum;

                记录真实的值则是用户的真实数据,当然,该区域有几个隐藏字段相当重要:DB_ROW_ID,当一张表中没有主键时,会默认的将该字段当成ID,也会给该ID创建B+树当作主键索引;DB_TRX_ID,事务ID,MVCC的实现则依赖该字段,undo页中则存储的了改字段;DB_ROLL_PTR回滚指针,当需要回滚时,则会使用该字段.

        2、InnoDB的内存结构(默认128MB)

                (1)Buffer Pool

                InnoDB专用缓存,用来缓存表对象的数据和索引信息的。Page页之间通过链表结构进行管理,包括free list(空闲链表)可以当作缓存用的链表、flush list(刷新链表)对一些缓冲页进行修改(脏页),需要定期书信到磁盘上ush链表和LRU list根据数据页的访问时间会将数据页排列在LRU链表中,对LRU上的页进行清除时,会从末尾开始,

                LRU:LRU链表被midpoint节点分为两个链表young链表,old链表,新读取的页会先被放到midpoint节点,后续将根据访问情况分别添加至young或old,再根据时间淘汰old链的末尾页

                (2)Change Pool

                用于缓存对不在Buffer Pool中的非主键索引页的更新操作,以减少对磁盘的随机读取。

                (3)Log Buffer

                用于缓存即将写入磁盘的redo log和undo log日志数据。它减少了磁盘IO操作,提高了日志写入效率。

四、索引

        1、B+树索引结构

                B+树的特点:所有数据存储在叶子节点,非叶子节点仅存储索引。每个节点都是一页,

其中再每页中会有下个节点的页偏移量

        2、索引分类

                聚簇索引(主键索引):主键索引会包含此页中所有数据的列

                二级索引:主键索引之外的都叫二级索引,包含组合索引等,组合索引是一种特殊的二级索引,在B+树的叶节点上都没有完整的数据,二级索引由于没有一行中的所有字段数据(只包含索引字段和主键字段,主键字段没有的话,前面提到的DB_ROW_ID会当成默认的主键),所以当根据索引字段进行查询时,会先通过索引字段匹配到具体的主键,再根据主键去 聚簇索引中找到详细的数据(此过成叫回表),联合索引:当二级索引B+树的匹配列大于二就时组合索引,其中如果需要同事根据两个条件进行比较,会按照最左匹配原则找到对应的数据ID,再去主键索引中找到对应的数据,避免了两个条件多次回表的情况(索引下推);当需要得到的数据可以直接在组合索引中找到,比如ID,就不会进行回表(覆盖索引)

五、日志

        Bin-Log(server)逻辑日志:

         binlog时mysql服务层面的日志文件,默认不开启,可以在my.ini文件中手动开启,可以通过show binlog events;命令查看binlog,当然在data目录下存在这个具体的文件,可以使用命令(mysqlbinlog)将文件转化为可读的状态,再进行查看,binlog只会记录增删改的记录,binlog会不断的累计日志的写入模式如下:

                statement(默认记录方式):记录SQL,会有一定风险

                row:记录具体的行数据

                mixed:以上两种结合

        应用场景:数据归档,主从备份,恢复到指定时间

        Redo-Log(存储引擎)物理日志:

        redolog也记载的是执行的数据变动,不同的是redolog记录的是数据页的变动,而不是具体的sql,

redolog有固定的大小,可以自己设置,会使用一个文件组的策略,循环的复写这个文件组去提升利用率,文件组一个重要的概念是check_point用于标记可以复写的位置.

        redolog的主要应用场景是故障的恢复,因此只需要记录更新的日志,也就是产生脏页的数据,事务提交的时候redolog是一定会刷盘的,具体就是先将脏页更新到logBuffer中再进行刷盘到redolog,每一个存在数据修改的事务redolog都能保证,当提交事务时,脏页再内存中更新,并写入到redolog日志中,这里大家可能会有疑问,为什么不直接刷新到ibd文件而是刷新到redolog这样,等故障恢复还要将redolog中的数据加载到内存再刷新到ibd,不是多次一举吗,原因是,从flash链表刷新到redolog和ibd文件是不一样的,在redolog中是一个顺序写,而在ibd则有很大的概率是随机写,对性能的损耗很大.

        Undo-Log(存储引擎):

        undolog严格意义上讲是一种类型的页(undo页),他其中有两条链表,insert链表和updata链表,但它起到了日志作用,前面也有提到,它并不额外对应一个日志文件,所以它最终存储的位置是ibd文件中,undolog与事务回滚和MVCC(多版本并发控制)有关,所以是一种相当重要的日志,当修改一条数据时,innodb会将新增一条数据存在undolog,并用行中的回滚指针(Roll_point)连成链表形成版本链,再添加一份与当前数据相连在真正的页中,然后将值改为修改的值.

        对于不同的错做,undolog存的东西也不一样,undo页也是可以复用的页,因为当insert操作完成后,

                对于新增操作来说,undolog只会存储该行的ID值;

                对于修改的操作,则只记录修改前的旧值

                对于删除操作,会先将数据的deleted字段标记,做一个软删除,当事务提交时,会真正的删除数据

六、事务

        什么是事事务?

                由一组数据操作序列组成,数据操作之间是原子性的,也就是说要么同时成功,要么同时失败

        事务特性(ACID):

                原子性:表示一条事务中的操作要么同时成功,要么同时失败

                持久性:一旦事务被提交,它对数据库的修改就应该是永久性的,即使系统发生故障也不会丢失。

                隔离性:事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。这通过锁机制或并发控制机制来实现,以防止多个事务同时修改同一数据导致的冲突。

                一致性:事务必须使数据库从一个一致性状态变换到另一个一致性状态。即事务执行的结果必须保持数据的一致性,不会发生破坏数据完整性的情况。

        事务隔离级别:

                读未提交(READ UNCOMMITTED)

                        在该级别下即使事务未提交,对其他事务也是可见的,即一个事务可以读取另一个事务未提交的数据。(脏读)

                        存在的问题:脏读,幻读,不可重复读

                读已提交(READ COMMITTED)

                        这种隔离级别下,可以避免脏读,但可能会出现不可重复读(Non-repeatable Read),即在同一个事务中,连续两次读取同一数据可能会有不同的结果,因为其他事务可能在中间提交了修改。

                        存在的问题:幻读,不可重复读

                可重复读(REPEATABLE READ)

                        在这个级别下,事务在启动时,它会看到一个一致的数据快照,这意味着同一个事务中的所有读操作会看到同样的数据。这种隔离级别下,可以避免脏读和不可重复读。但在某些情况下,可能会出现幻读(Phantom Read),即在同一事务中,连续两次执行相同的查询,第二次查询可能会看到在第一次查询后由其他事务插入的新行。InnoDB 默认使用这一隔离级别,并通过多版本并发控制(MVCC)机制来避免幻读。

                        在特定情况下的 有幻读风险

                串行化(SERIALIZABLE)

七、MVCC(多版本并发控制)

        工作原理:

                确定那些比最新的事务要小并且已经提交的事务

        ReadView:

                为什么存在:为了确定应该使用版本链中的哪一个版本(判断一个DB_TRX_ID是已经提交的还是正在运行的)

                结构:

                        max_trx_id:下一个要分配的trx_id;

                        main_trx_id:所有的活跃中的版本中最小的ID;

                        m_ids:所有活跃的trx_id;

                        creator_trx_id:当前事务的ID(可能是0,因为当前可能没有执行到自己事务的写操作)

                原理:通过判断当前事务在哪一个区间里从而判断当时的版本能不能用

        RC在每次读操作时都会创建一个新的ReadView,因而不可重复读,

        RR在第一次读的时候会创建ReadView,除过自己写的值,其他事务读到的都是一个ReadView直到事务提交

        快照读:读某一时刻的数据

        当前读:每次读都是最新提交的数据(写的时候一般都是当前读)

        MVCC解决了可重复读的事务隔离级别和视图读下的幻读问题;

        当前读的幻读问题,需要锁来完成;

八、锁

        行锁主要解决了当前读的幻读问题

        行锁

                记录锁(ret_not_gap):给数据加锁,保证其他事务无法修改数据。
                        例如:update XXXX where id=1;
                间隙锁(gap):锁住一个区间,当前条目和前一条条目的间隙不包含当前条目。
                        例如q:update XXXX where id<1;
                临键锁:记录锁+间隙锁,包括当前条目都会被锁到。
                        例如:update XXXX where id<=1;
                以上三种锁保证不会出现并发写
                插入意向锁:在间隙锁中插入数据,会分配一个插入意向锁
                隐式锁:惰性的加记录锁的方式是隐式锁(insert)
                共享锁:  我占用了,其他的事务还可以读,不能写
                独占锁:我占用了,其他的事务无法读也无法写

        表锁

                操作: lock tables user READ;
                            lock tables user write;
                行锁和表锁有一定的互斥性
                类型:意向锁:
        自增锁:当insert这句SQL结束的时候释放锁(其他锁针对事务)
        MDL:(serve级别)修改表的结构加的该锁
        死锁:当互相争夺资源时出现死锁,死锁出现会报错,并向上报告

        

        

                

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值