MySQL体系结构和存储引擎
概念
数据库:物理操作系统文件或其他形式文件类型的集合,如frm、MYD、MYI、ibd结尾的文件。
实例:MySQL数据库由后台线程以及一个共享内存区组成。在系统上的表现就是一个进程。
MySQL体系结构
连接池组件
管理服务和工具组件
SQL接口组件
查询分析器组件
优化器组件
缓冲组件
插件式存储引擎
物理文件
MySQL存储引擎
存储引擎是基于表的,而不是数据库
InnoDB
主要面向在线事务处理(OLTP)应用,行锁设计、支持外键,支持类似于Oracle的非锁定读。
MyISAM
不支持事务、表锁设计,支持全文索引,主要面向(OLAP)应用。存储引擎表由MYD和MYI组成,MYD用来存放数据文件,MYI用来存放索引文件。
NDB
是一个集群存储引擎,数据全部放在内存中。
Memory
将表中的数据存放在内存中,如果数据库重启或发生崩溃,表中数据都将消失,适合存储临时数据以及数据仓库的纬度表。默认使用哈希索引。
Archive
只支持INSERT和SELECT操作,使用zlib算法将row压缩后存储,适合存储归档数据。
InnoDB存储引擎
体系架构
后台线程
Master Thread
主要负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性,包括脏页的刷新、合并插入缓冲、UNDO页的回收等。
IO Thread
InnoDB中大量使用了AIO来处理IO请求,IO Thread的工作主要是负责这些IO请求的回调处理。
通过`SHOW ENGINE INNODB STATUS`可以查看。
Purge Thread
使用Purge Thread回收已经使用并分配的undo页。
可以在配置文件中通过`innodb_purge_threads`参数设置线程数量。
Page Cleaner Thread
主要工作是脏页的刷新,为了减轻Master Thread的工作及对于用户查询线程的阻塞,进一步提高InnoDB的性能。
内存
缓冲池
通过内存的速度来弥补磁盘对数据库性能的影响
读取:从磁盘读到的页存放在缓冲池中,下一次读到相同页,若命中,直接读取该页。
修改:首先修改缓冲池中的页,然后再以一定频率刷新到磁盘。
通过`innodb_buffer_pool_size`来设置缓冲池大小
LRU List、Free List和Flush List
LRU List
InnoDB中,缓冲池使用LRU算法来管理。不一样的是加入了midpoint位置,新读取到的页,并不是直接放入到LRU列表到首部,二是放入到LRU的midpoint位置。默认该位置在LRU列表的5/8处,可以由`innodb_old_blocks_pct`参数控制。
midpoint之后的列表称为old列表,之前的列表称为new列表。可以简单理解new列表中的数据都是最活跃的热点数据。
缓冲池中页的大小默认是16KB
Free List
LRU列表用来管理已经读取的页,数据库刚启动时,LRU列表为空,这时的页都存放在Free列表中。当需要从缓冲池中分页时,先从Free列表中查找是否有可用的空闲页,若有则将该页从Free列表中删除放入LRU列表中,否则根据LRU算法,淘汰LRU列表末尾的页。
Flush List
在LRU列表中的页被修改后,该页为脏页,即缓冲池中的页和磁盘上页的数据产生了不一致。这时数据库会通过CHECKPOINT机制将脏页刷新回磁盘。Flush列表中的页即为脏页列表。
脏页即存在于LRU列表中,也存在于Flush列表中。LRU列表用来管理缓冲池中页的可用性,Flush列表用来管理将页刷新回磁盘
重做日志缓冲
将重做日志信息先放入这个缓冲区,然后按一定频率将其刷新到重做日志文件。一般每秒钟会刷新一次。
该值可以由参数`innodb_log_buffer_size`控制,默认8MB。
刷新触发条件
Master Thread每秒刷新一次;
每个事务提交时;
当重做日志缓冲池剩余空间小于1/2时。
额外的内存池
CheckPoint技术
如果每次一个页发生变化就将该页的数据刷新到磁盘的开销非常大。为了保证数据库性能又避免数据丢失,采用Write Ahead Log策略。先写重做日志,再修改页。
CheckPoint技术的目的是为了解决
缩短数据库的恢复时间;
缓冲池不够用时,将脏页刷新到磁盘;
重做日志不可用时,刷新脏页。
当数据库发生宕机时,只需要对Checkpoint后的重做日志进行恢复,这样大大缩短了恢复时间。
两种CheckPoint
Sharp Checkpoint
发生在数据库关闭时将所有的脏页都刷新回磁盘。
Fuzzy Checkpoint
Master Thread Checkpoint
每秒或每10秒刷新一定比例的页。
FlUSH_LRU_LIST Checkpoint
InnoDB要保证LRU列表中有100个空闲页可以使用,如果少于100个,会将LRU列表尾端的页移除。如果这些页有脏页,则需要进行Checkpoint。
Async/Sync Flush Checkpoint
重做日志文件不可用时,强制将一些页刷新回磁盘。
Dirty Page too much Checkpoint
脏页太多了。通过参数`innodb_max_dirty_pages_pct`控制,默认值75。
Master Thread 工作方式
Master Thread具有最高的线程优先级别。
内部由多个循环组成
主循环
每秒操作
日志缓冲刷新到磁盘,即使这个事务还没提交(总是);
合并插入缓冲(可能);如果前一秒的IO次数小于5次,则认为当前IO压力很小,可以执行合并插入缓冲的操作。
至多刷新100个InnoDB的缓冲池中的脏页到磁盘(可能);通过判断当前缓冲池中的脏页比例是否超过`innodb_max_dirty_pages_pct`配置的值。
如果当前没有用户活动,切换到background loop(可能)。
10秒操作
刷新100个脏页到磁盘(可能);
合并至多5个插入缓冲(总是);
将日志缓冲刷新到磁盘(总是);
删除无用的Undo页(总是);
刷新100个或者10个脏页到磁盘(总是);
在1.2.x版本以后,刷新脏页的操作分离到单独的Page Cleaner Thread操作。
后台循环
删除无用的Undo页(总是)
合并20个插入缓冲(总是);
跳回到主循环(总是);
不断刷新100个页直到符合条件(可能,跳转到flush loop中完成)。
刷新循环
暂停循环
InnoDB关键特性
插入缓冲
Insert Buffer
对于非聚集索引的插入或更新操作,不是每次直接插入到索引页中,而是先判断插入的非聚集索引页是否在缓冲池中,若在,则直接插入,否则先放入Insert Buffer中。然后再以一定的频率进行Insert Buffer和辅助索引页字节点的merge操作。
Insert Buffer的使用需要同时满足
索引是辅助索引
索引不是唯一的
目前Insert Buffer错在一个问题是:在写密集的情况下,插入缓冲会占用过多的缓冲池内存,默认可以占到1/2
Change Buffer
1.0.x版本后引入,相当于Insert Buffer的升级
Insert Buffer
INSERT
Delete Buffer
DELETE
Purge Buffer
UPDATE
Insert Buffer的内部实现
一颗全局的B+树,负责对所有表的辅助索引进行Insert Buffer。存放在共享表空间中。
两次写
insert buffer带来性能提升,double write可以给数据页带来可靠性。
在对缓冲池的脏页进行刷新时,并不直接写磁盘,而是通过memcpy将脏页先复制到内存中的doublewriter buffer,之后通过doublewriter buffer再分两次,每次1MB顺序写入共享表空间的物理磁盘,然后马上调用fsync同步磁盘,避免缓冲写带来的问题。
因为doublewrite页是连续的,因此这个过程是顺序写,开销不会很大。
自适应哈希索引
哈希索引只能用来搜索等值查询
异步IO
提高磁盘操作性能
刷新邻接页
当刷新一个脏页时,innodb会检测该页所在的区的所有页,如果是脏页,会一起刷新。
文件
参数文件
MYSQL可以不用参数文件,编译时或代码中有指定默认值
日志文件
错误日志
SHOW VARIABLES LIKE 'log_error'来定位文件为止
慢查询日志
定位可能存在问题的SQL语句
写入慢查询通过参数long_query-time来设置,默认10s
默认不开启,通过long_slow_queries = ON开启
long_queries_not_using_indexes = ON时,没使用索引的SQL也会写入慢查询日志
log_throttle_queries_not_using_indexes表示每分钟允许记录到slow log的且未使用索引的SQL语句次数,默认为0,表示不限制
mysqldumpslow查询慢查询日志
查询日志
记录所有对MySQL请求的信息,无论这些请求是否得到正确的执行。
二进制日志
记录对数据库执行更改的所有操作,但不包括SELECT和SHOW。UPDATE如果没改变数据不一定会写入binlog
binlog作用
恢复
复制
比如主从复制
审计
对db数据审计,判断是否有数据库注入攻击
所有未提交的binlog会记录到缓存中,事务提交时直接将缓冲内的binlog写入到binlog文件中。缓冲区大小由binlog_cache_size决定,默认32K。
当一个线程开始一个事务时,会自动分配一个大小为binlog_cache_size的缓存
sync_binlog=N
表示写缓冲多少次就同步到磁盘
1,表示同步写
0,默认,表示不开启
mysqlbinlog用来查看binlog
socket文件
pid文件
表结构定义文件
以frm为后缀的文件,记录了表结构定义
存储引擎文件
表空间文件
innodb将存储的数据按表空间进行存放,默认会有一个初始大侠送为10MB,名为ibdata1的文件。
innodb_file_per_table,表示将每个基于表产生一个独立表空间
单独的表空间仅存储该表的数据、索引和插入缓冲BITMAP等信息。其余信息还是存在默认的表空间
redo日志文件
一条记录更新时,InnoDB会先把记录写到redo log里面,并更新内存。在适当的时候,将这个记录更新到磁盘。(WAL技术)
redo log是固定大小的,从头开始写,写到末尾又回到开头循环写,write pos是当前记录的位置,一边写一边后移。checkepoint是当前要擦除的位置,擦除前要把记录更新到磁盘。
如果write pos追上checkepoint,不再执行新的更新,得先擦掉一些记录,将checkpoint推进一下。
与binlog的区别
redo log是InnoDB特有;binlog是Server层实现,所有引擎都有。
redo log是物理日志,记录的是某个数据页上做了什么修改;binlog是逻辑日志,记录的是这个语句的原始记录
redo log是循环写,空间固定会用完;binlog是追加写入,写到一定大小会切换到下一个,并不会覆盖以前的日志。
binlog仅在事务提交前进行提交,只写磁盘一次;而在事务进行的过程中,不断有重做日志条目写到redolog
表
索引组织表
innodb中,表都是根据主键顺序组织存放
如果没有显式定义主键
首先判断表中是否有非空的唯一索引,如果有,该列即为主键。
如果有多个非空唯一索引,选择建表时第一个定义的非空唯一索引为主键
否则自动创建一个6字节大小的指针
innodb逻辑存储结构
表空间
innodb存储引擎逻辑结构的最高层,所有数据都存放在表空间中
段
数据段即为B+树的叶子节点
索引段即为B+树的非索引节点
区
区是由连续页组成的空间,在任何情况下,每个区的大小都是1MB
默认一个页大小是16KB,一个区即64个页
页的大小可以通过innodb_page_size设置
页
innodb磁盘管理的最小单位
行
每个页最多允许存放16KB/2 - 200行记录,即7992行。
innodb行记录格式
compact格式
变长字段长度列表
若列小于255字节,1字节表示。否则2字节表示
因为VARCHAR最大长度限制是65535
数据是逆序存放
NULL标志位
指示该行数据中是否有NULL,有则用1表示
记录头信息
5字节
隐藏列
事务ID
6字节
回滚指针
17字节
若没定义主键,会增加6字节rowid
Redundant格式
字段长度偏移列表
与compact长度列表一样,也是逆序存放
记录头信息
6字节
行溢出数据
一般情况,innodb的数据都存放在b-tree node中,但发生行溢出时,数据存放在uncompress BLOB二进制大对象页中
BLOB、LOB不一定放在溢出页面,VARCHAR可能存放在溢出页面
VARCHAR实际最大长度只能是65532,起始位和结束位占3个字节
且是所有VARCHAR列长度,如果列长度总和超过这个长度,依然无法创建表
InnoDB数据页结构
File Header
记录页的一些头信息
Page Header
记录数据页的状态信息
Infimun和Supermum Records
Infimum记录比该页中任何主键值都小的值
Supermum指比任何可能大的值都要大的值
这两个值在页创建时被建立,任何情况下不会被删除
User Records
即行记录
Free Space
是一个链表,一条记录被删除后,该空间会被加入到空闲链表
Page Directory
存放记录的相对位置
B+树索引本身并不能找到具体的一条记录,能找到该记录所在的页。数据库把页载入内存,然后通过Page Direcrory再进行二叉查找。
File Trailer
8字节,前4字节代表该页的checksum值,后4字节代表该页最后被修改的日志序列位置LSN
每次从磁盘读取一个页会通过File Trailer检测该页的完整性
可以通过innodb_checksums来开启或关闭页完整性检测
Named File Formats机制
用于解决不同版本下页结构兼容性的问题
约束
数据完整性
实体完整性保证表中有一个主键
域完整性保证数据每列的值满足特定的条件
innodb的约束
Primary Key
Unique Key
Foreign Key
Default
NOT NULL
约束的创建和查找
表建立时就进行约束定义
利用ALTER TABLE来创建约束
约束和索引的区别
约束是一个逻辑概念,用于保证数据的完整性
索引是一个数据结构,既有逻辑上的概念,在数据库中还代表中物理存储的方式
ENUM和SET约束
触发器与约束
作用是在执行INSERT、DELETE和UPDATE之前或之后自动调用SQL语句或存储过程
创建命令:CREATE TRIGGER
一个表最多可以建立6哥触发器,INSERT、DELETE和UPDATE的BEFORE和AFTER各一个
外键约束
用于保证参照完整性
视图
视图是一个命名的虚表,由一个SQL查询来定义,没有实际物理存储。
物化视图
基于实际存在的实表,数据存储在非易失的存储设备上
可用于预先计算并保存多表的JOIN或GROUP BY等耗时比较多的SQL操作结果
对于一些复杂的统计类查询能直接查出结果
创建方式
BUILD IMMEDIATE
BUILD DEFERRED
分区表
概述
分区的过程是将一个表或索引分解成多个更小、更可管理的部分
mysql只支持水平分区不支持垂直分区
分区类型
不论何种类型分区,如果表中存在主键或唯一索引时,分区列必须是唯一索引的一个组成部分
RANGE分区
根据列值的范围分区
LIST分区
与RANGE类似,只是列的值是离散的
HASH分区
HASH分区的目的是将数据均匀的分布到预定义的各个分区中,保证分区数据量均衡
KEY分区
利用MYSQL提供的函数进行分区
COLUMNS
前面的分区类型要求数据必须是整型,COLUMNS可以直接使用非整型的数据进行分区
子分区
RANGE和LIST分区上还可以进行HASH和KEY子分区
分区和性能
OLTP分区可能反而会使应用执行得更慢
索引和算法
概述
类型
B+树索引
B+树的B不是binary,而是balance
B+树索引能找到的只是被查找数据行所在的页,然后数据库通过把页读入到内存,再在内存中进行查找
全文索引
哈希索引
B+树
所有记录节点都是按键值的大小顺序存放在同一层的叶子节点上,由各叶子节点指针进行连接
B+树索引
聚集索引
按照每张表的主键构造一颗B+树,叶子节点存放的为整张表的行记录数据,叶子节点称为数据页
每张表只能有一个聚集索引
辅助索引
叶子节点不包含行记录的全部数据,包含的是主键
每张表可以有多个
通过辅助索引来寻找数据时,Innodb存储引擎会便利辅助索引获取到指向主键索引的主键,然后再通过主键索引找到完整的行记录,这个过程叫回表
索引管理
创建/删除
ALTER TABLE
CREATE/DROP INDEX
Fast Index Creation
快速索引创建
辅助索引创建时,对表加上S锁,因此在创建的过程中只能对该表读操作
Online DDL
原理是执行创建或删除操作时,将INSERT、UPDATE、DELETE这类DML操作日志写入一个缓存中。完成索引创建后再将redo应用到表上
Cardinality值
索引中不重复数记录数量到预估值
Cardinality/n_rows_in_table应尽可能接近1
更新
采样统计
表中1/6的数据发生过变化时
修改的行超过20亿次时,行内容不一定要改变
B+树索引的应用
联合索引
指对表上的多个列进行索引
联合索引的键值数量大于2
覆盖索引
即从辅助索引中就可以得到查询的记录
辅助索引不包含整行记录的所有信息,故大小要远小于聚集索引,可以减少大量的IO操作
索引提示
SELECT时通过USE INDEX指定
USE INDEX只是告诉优化器可以选择该索引,实际上优化器还是会根据自己的判断进行选择
如果需要明确指定某个索引则使用FORCE INDEX
哈希算法
innodb采用除法hash方式
自适应哈希索引
数据库自身创建并使用,DBA不能对其进行干预
全文检索
全文检索是将存储于数据库中的整本书或整篇文章中的任意内容查找出来
倒排索引
全文检索通常使用倒排索引来实现
在辅助表中存储来单词和单词自身在一个或多个文档中所在位置之间的映射
innodb全文检索
限制
每张表只能有一个全文检索索引
由多列组合而成的全文检索索引列必须使用相同的字符集与排序规则
不支持没有单词界定符的语言,如中文、日语、韩语等
语法
MATCH() ··· AGAINST()
锁
锁用于管理对共享资源的并发访问
lock和latch
latch是轻量级的锁,要求锁定的时间必须非常短
mutex
rwlock
用于保证并发线程操作临界资源的正确性,通常没有死锁检测的机制
lock的对象是事务,用来锁定的是数据库中的对象,如表、页、行。
Innodb中的锁
锁的类型
共享锁(S Lock)允许事务读一行数据
排他锁(X Lock)允许事务删除或更新一行数据
意向锁
即为表级别的锁,设计的目的为了在一个事务中揭示下一行将被请求的锁类型。
类型
意向共享锁(IS Lock)事务想要获得一张表中某几行的共享锁
意向排他锁(IX Lock)事务想要获得一张表中某几行的排他锁
可以通过SHOW ENGINE INNODB STATUS查看当前锁请求的信息
一致性非锁定读
指innodb通过多版本控制的方式来读取当前执行时间数据库中行的数据。如果读取的行正在DELETE或UPDATE,这时读取不会去等待行上锁的释放,而是读取行的快照数据
一个行记录可能有不止一个快照数据
事务隔离级别为REPEATABLE READ模式以下,SELECT操作使用一致性非锁定读
一致性锁定读
两种一致性锁读
SELECT FOR UPDATE
加X锁
SELECT LOCK IN SHARE MODE
加S锁
自增长与锁
自增长计数器采用AUTO-INC Locking实现
为了提高插入性能,锁不是一个事务完成后才释放,而是完成自增长插入SQL语句以后立即释放
Innodb中,自增长值必须是索引,且必须是索引的第一列
外键和锁
对于外键列,如果没有显式加索引,innodb会自动加一个索引,可以避免表锁
对外键值的插入或更新,会对父表加一个S锁。如果这时父表加了X锁,子表对操作会被阻塞
锁的算法
Record Lock
单行记录上的锁
Gap Lock
锁定一个范围,但不包含记录本身
为了阻止多个事务将记录插入到同一范围内,但是会导致幻读现象
关闭Gap Lock
将事务的隔离级别设置为READ COMMITTED
将参数innodb_locks_unsafe_for_binlog设置为1
Next-Key Lock
Gap Lock + Record Lock,锁定一个范围,并且锁定记录本身
当查询当列是唯一索引时,Next-Key Lock会降级为Record Lock
解决幻读
幻读指同一事务下,连续执行两次同样的SQL语句可能会有不同的结果。第二次的SQL语句可能会返回之前不存在的行
采用Next-Key Lock解决
锁问题
脏读
指在不同的事务下,当前事务可以读到另外事务未提交的数据
脏页与脏数据
脏页指在缓冲池中已经被修改读页,但还没有刷新到磁盘中,而脏数据指事务对缓冲池中行记录对修改,并且还没有被提交
脏页读取是正常的,而脏数据读取指读取到未提交到数据,违反了数据库到隔离性
脏读发生的条件是隔离级别未READ UNCOMMITTED,所以只要隔离级别大于RUC即可解决
不可重复读
指一个事务内多次读取同一个数据集合,在这个事务还没结束时,另外一个事务也访问该同一数据集合,并做了一些DML操作。那么这个事务两次读到的数据可能不一样
不可重复读和脏读区别
脏读是读到未提交的数据
不可重复读读到的是已经提交的数据,但违反了数据库事务一致性的要求
在Next-key lock算法下,对于索引的扫描,不仅是锁住扫描的索引,而且还锁住这些索引覆盖的范围。因此在这个范围内的插入都是不允许的,这样就避免了另外的事务在这个范围内插入数据导致的不可重复读的问题。
丢失更新
指一个事务的更新操作会被另一个事务的更新操作所覆盖,从而导致数据不一致
避免丢失更新发生,需要让事务串行化
阻塞
指一个事务中的锁需要等待另一个事务中的锁释放它所占的资源
通过innodb_lock_wait_timeout来控制等待时间
死锁
死锁指两个或者两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象
解决死锁问题最简单的方式是超时,当两个事务互相等待时,其中一个超时回滚,另一个就能继续进行。
采用wait-for graph的方式来进行死锁检测
锁升级
指将当前锁的粒度降低
触发锁升级条件
由一句单独的SQL语句在一个对象上持有的锁的数量超过来阈值(默认5000)
锁资源占用的内存超过来激活内存的40%时
innodb不存在锁升级的问题,因为其不是根据每个记录来产生行锁的,而是根据每个事务访问的每个页对锁进行管理的,采用的是位图的方式。因此不管一个事务锁住页中多少记录,其开销通常都是一致的。
事务
事务是访问并更新数据库中各种数据项的一个持续执行单元。在事务中的操作,要么都修改,要么都不修改。
事务分类
扁平事务
所有操作处于同一层次,期间操作是原子的
带有保存点的扁平事务
允许在事务执行过程中回滚到同一事务中较早的一个状态
链事务
与👆的类似,带有保存点的扁平事务能回滚到任意正确的保存点,链事务只能回滚到最近的一个保存点
嵌套事务
一个层次结构,由顶层事务控制这各各层次的事务
分布式事务
在一个分布式环境中运行的扁平事务
事务的实现
redo log
基本概念
redo log用来实现事务的持久性,即ACID中的D
由内存中的redo log buffer和redo log file组成
当事务提交时,必须先将该事务的所有日志写入到redo log文件进行持久化
基本都是顺序写,在数据库运行时不需要对redo log的文件进行读取操作
innodb_flush_log_at_trx_commit用来控制redo log刷新到磁盘的策略
默认为1
事务提交时必须调用一次fsync
0
事务提交时不进行写入redo log操作,只在master thread中每秒fsync一次
2
事务提交时写入redo log,但仅写入文件系统的缓存中。不进行fsync操作
log block
redo log buffer和redo log file都是以块的方式存储的,每块大小512字节
由于redo log block和磁盘扇区大小一样,因此redo log的写入可以保证原子性,不需要doublewrite技术
log group
由多个redo log file组成,每个日志文件大小相同
log buffer刷新到磁盘规则
事务提交时
当log buffer中有一半当内存空间已经被使用时
log checkpoint时
redo log格式
头部格式
redo_log_type
space
表空间的ID
page_no
页的偏移量
LSN
日志序列号,8个字节,单调递增,表示事务写入redo log的字节总量
含义
redo log写入的总量
checkpoint的位置
页的版本
恢复
innodb在启动时不管上次数据库是否正常关闭,都会尝试进行恢复操作
undo log
基本概念
与redo log存放在日志文件中不同,undo存放在数据库内部的一个特殊的段中,即undo段。位于共享表空间内
用来保证事务的一致性
用来帮助事务回滚及MVCC
undo log是需要进行随机读写的
undo是逻辑日志,只是将数据库逻辑地恢复到原来的样子,所有修改都被逻辑地取消了,但数据结构和页本身在回滚之后可能大不相同
undo存储管理
innodb有一个rollback segment,每个回滚段中记录了1024个undo log segment,每个undo log segment中进行undo页的申请
事务提交时,undo处理
将undo log放入列表中,以供之后的purge操作
判断undo log所在的页是否可以重用,若可以分配给下个事务使用。
事务提交后并不能马上删除undo log及其所在的页。因为可能还有其它事务需要通过undo log来得到行记录之前的版本。是否能够最终删除,由purge线程来判定
undo log格式
insert undo log
在insert操作中产生的,由于insert操作的记录只在本事务中可见,该undo log可以在事务提交后直接删除
update undo log
delete和update产生的,可能需要提供MVCC机制,因此不能在事务提交时进行删除。提交时放入undo log 链表,等待purge线程进行最后删除。
purge
用于最终完成delete和update操作
由于innodb支持MVCC,可能在事务提交时其它事务正在引用这行,故需要保存之前的版本。若该行记录已不被任何其它事务引用,那么就可以进行真正的delete。
group commit
即一次fsync可以刷新确保多个事务日志被写入文件
事务提交的两阶段操作
参考:https://jin-yang.github.io/post/mysql-group-commit.html
事务控制语句
START TRANSACTION | BEGIN
显示开启一个事务
COMMIT
提交事务,并对数据库进行所有修改成为永久性的
ROLLBACK
结束事务,并撤销正在进行的所有未提交的修改
SAVEPOINT
创建一个保存点,一个事务中可以由多个保存点
RELEASE SAVEPOINT
删除一个事务的保存点
ROLLBACK TO [SAVEPOINT]
把事务回滚到保存点
SET TRANSACTION
设置事务的隔离级别
事务的隔离级别
读未提交
select不加锁,可能出现读脏
读提交
普通select快照读,锁select /update /delete 会使用Record Lock,可能出现不可重复读
可重复读
innodb默认
普通select快照读,锁select /update /delete 根据查询条件情况,会选择Record Lock,或者Gap Lock / Next-key Lock,以防止幻读
串行化
select隐式转化为select ... in share mode,会被update与delete互斥
备份与恢复
备份的方法
冷备
数据库停止时备份,最为简单,一般只需要复制相关的数据库物理文件即可
热备
数据库运行中直接备份,并且对运行中对数据库操作没有任何影响
子主题 2
温备
数据库运行中进行,但会对当前数据库对操作有所影响。如加一个全局读锁以保证备份数据对一致性
备份后文件内容
逻辑备份
指备份出的文件内容时可读的,一般为文本文件,内容为一条条SQL语句或者表内实际数据
如mysqldump和SELECT * INTO OUTFILE
裸文件备份
指复制数据库的物理文件
如ibbackup、xtrabackup这类工具
备份的内容
完全备份
增量备份
日志备份
通过binlog备份
mysql的复制
复制是mysql通过高可用解决方案
步骤
master把数据更改记录到binlog中
slave把master的binlog复制到自己的relay log中
slave重做relay log中的日志,把更新应用到自己的数据库中,以达到数据一致性