怎么建设电子商城网站,湘潭关键词优化公司,网络科技公司销售是做什么的,公司部门有哪些InnoDB引擎是MySQL5.5版本之后默认的存储引擎
逻辑存储结构
首先是表空间Tablespace#xff08;ibd文件#xff09;#xff1a;一个mysql实力可以对应多个表空间#xff0c;用于存储及记录#xff0c;索引等数据
这些存储记录#xff0c;索引等数据中是用段(Segment)来…InnoDB引擎是MySQL5.5版本之后默认的存储引擎
逻辑存储结构
首先是表空间Tablespaceibd文件一个mysql实力可以对应多个表空间用于存储及记录索引等数据
这些存储记录索引等数据中是用段(Segment)来存储的 段分为
数据段Leaf node segment索引段Non-leaf node segment回滚段Rollback segment
InnoDB是索引组织表数据段就是B树的叶子节点索引段即为B树的非叶子节点
段用来管理多个区Extent
区表空间的单元结构每个区为1MB默认情况下InnoDB存储引擎页的大小是16KB即一个区中又64个页Page
页是InnoDB存储引擎磁盘管理的最小单元每个页的大小默认是16KB为了保证页的连续性InnoDB存储引擎每次从磁盘申请4-5个区
页中存放的是行RowInnoDB存储引擎数据是按行进行存放的
如表中的隐藏字段 Trx_id:每次对某条记录进行改动时都会把对应的十五id赋值给trx_id隐藏列 Roll_pointer:每次对某条印记路进行改动时都会把旧的版本写入到undo日志中然后这个隐藏列相当于一个指针同故宫他来找到该记录修改前的信息
架构
InnoDB引擎是MySQL5.5版本之后默认的存储引擎他擅长事务处理具有崩溃恢复特性在日常中使用非常广泛
首先介绍InnoDB的内存结构 Buffer Pool
缓冲池时主内存的区域里面可以缓存磁盘上经常操作的真实区域在执行CRUD操作时前操作缓存池中的数据(如果没有那么久从磁盘上加载并且缓存)然后再以一定频率刷新到磁盘从而减少磁盘IO加快处理速度
这么做的原因是如果每次都是磁盘操作那么就会出现大量的磁盘IO而且是随机IO这样非常消耗性能
缓冲池以Page页为单位底层采用链表数据结构管理Page根据状态将Page分为三种类型
free page空闲page 未被使用过clean page被使用过但是数据没修改dirty page脏页被使用过page数据被修改过与磁盘内的数据不一致
Change Buffer
更改缓冲区(针对于非唯一二级缓存页)5.x的版本是一个叫Insert Buffer的东西8.0才出现的
再执行DML语句时如果这些数据Page没有在Buffer Pool中不会直接操作磁盘而会将数据变更存在更改缓冲区Change Buffer中在未来数据被读取时再将数据合并恢复到缓冲池中再将合并后的数据刷到磁盘上
Change Buffer的意义 与聚集索引不同二级索引通常是非唯一的并且相对随机的顺序插入二级索引同样删除和更新可能会影响所引述中不相邻的二级索引页如果每一次都操作磁盘会造成大量的磁盘IO有了ChangeBuffer之后我们在缓冲池中进行合并处理减少IO
Adaptive Hash Index
自适应Hash索引用于优化对Buffer Pool数据的查询InnoDB存储引擎会监控对表上各索引的插叙如果换查到hash索引可以提升速度则建立hash索引称为自适应hash索引
自适应哈希索引无需人工干预是系统根据情况自动完成
Log Buffer
日志缓冲区用来保存要写入到磁盘中的log日志数据(redo logundo log)默认大小为16MB日志缓冲区的日知会定期刷新到磁盘中如果需要更新插入或删除许多行的事务增加日志缓冲区的大小可以节省磁盘IO 可以配置缓冲区大小和日志刷新到磁盘的时机
磁盘结构 System Tablespace:
系统表空间是更改缓冲区的存储区域如果是在系统表空间而不是每个表文件或通用表文件创建的他也可能包含表和索引数据,(在5.X版本中还包含InnoDB数据词典undolog等)
File-Per-Table Tablespaces:
每个表的文件表空间包含单个InnoDB表的数据和索引兵存储在文件系统上的单个数据文件中
General Tablespace
通用表空间是手动创建的而不是系统自带的需要通过CREATE TABLESPACE语法创建通用表空间在创建时可以指定该表空间 如
# 创建一个通用表空间ts_xx, 这个表空间对应的磁盘文件xxx.ibd
create tablespace ts_xx add datafile xxx.ibd engine innodb;# 创建一个表xxx他的表空间是上面创建的ts_xx
create table xxx(id long primary key auto_increment , name varchar(20)) engine innodb tablespace ts_xx;Undo Tablespaces
撤销表空间MySQL实例在初始化时会自动创建两个默认的undo表空间(初始大小16M),用于存储undo log日志
Temporary Tablespaces
InnoDB使用绘画临时表空间和全局临时表空间存储用户创建的临时表等数据
Doublewrite Buffer Files
双写缓冲区innoDB引擎将数据页从Buffer Pool刷新到磁盘前先将数据页写入双鞋缓冲区文件中便于系统异常时恢复数据
Redo Log
重做日志是用来实现事务的持久性该日志文件由两部分组成重做日志缓冲(redo log buffer) 以及重做日志文件(redo log)前者时在内存中后者在磁盘中。当事务提交之后会把所有修改信息都会存到该日志中用于在刷新脏页到磁盘时发生错误后进行数据回复 事务持久性依赖于该日志
分别介绍了内存和磁盘结构那么就需要把两个结构连接起来而后台线程就是把他们连接起来的工具
后台线程
后台线程的作用就是把InnoDB存储引擎缓冲池的数据在合适的时间刷新到磁盘文件中
后台线程分为四种
1. Master Thread
核心后台线程负责调度其他线程还负责将缓冲池中的数据异步刷新到磁盘中保持数据的一致性还包括脏页的刷新合并插入缓存undo页的回收
2. IO Thread
在InnoDB存储引擎中大量使用了AIO(异步非阻塞)来处理IO请求这样可以极大地提高数据库的性能而IO Thread主要负责这些IO请求的回调
IO Thread又包括四种
Read Thread 负责读操作默认4个Write Thread负责写操作页默认4个Log Thread负责将日志缓冲区刷新到磁盘默认1个Insert Buffer Thread负责将缓冲区内容刷新到磁盘默认1个
下面是如何查看状态
show engine innodb status;然后直接去找FILE I/O就可以看到IO线程了
3. Purge Thread
主要用于回收事务已经提交了的undo log 在十五提交之后undo log 可能不用了就用它来回收
4. Page Cleaner Thread
协助 Master Thread 刷新脏页到磁盘的线程可以减轻MT的工作压力减少阻塞
InnoDB事务的原理
InnoDB引擎很重要的一个功能就是支持了事务
事务是一组操作的集合他是一个不可分割的工作单位事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求及这些操作要么同时成功要么同时失败
事务的四大特性ACID
原子性(Atomicity): 事务时不可分割的最小单元同时成功或同时失败
一致性(Consistency): 事务完成时必须使所有的数据都保持一致状态
隔离性(Isolation): 数据库系统提供的隔离机制保证事务在不受外部并发操作影响的独立环境下运行
持久性(Durability): 事务一旦提交或回滚他对数据库中的数据改变就是永久的
隔离性又涉及到了隔离级别读未提交读已提交可重复读串行化默认可重复读
事务的原理
对于原子性一致性持久性来说在InnoDB中是由redo log 和 undo log来保证的 隔离性是由锁机制和MVCC(多版本并发控制)来保证的
redo log保证持久性
redo log 重做日志记录的事务提交时数据页的物理修改使用来实现事务的持久性的 该日志文件由两部分组成重做日志缓冲(redo log buffer)以及重做日志文件(redo log)前者是在内存中后者在磁盘中 当事务提交之后会把所有修改信息都存到日志文件中用于刷新脏页到磁盘发生错误时进行数据恢复使用
过程 当事务的请求发送给数据库时首先会看看内存的缓冲池有没有相对的数据没有的话要去磁盘里面读出来加载到缓存中 当缓存池中页的数据被进行了更改就会形成脏页会在下次对磁盘进行读写的时候给更改进去 但如果脏页的数据刷新到磁盘的过程出错了此时内存数据没刷新进去但是事务已经提交了这时候 - 由于磁盘数据与事务的数据不同那么持久性就没得到保证
为了保证事务一致性就出现了redo log与刚才的直接提交的操作不同他会先把脏页给到内存中的Redolog Buffer一份 当客户端事务提交之后RedologBuffer会向磁盘内提交数据页变化持久性的保持在磁盘文件中 在这之后如果脏页刷新到磁盘文件失败的话他可以通过redo log来进行恢复
事务提交时直接刷新ibd和直接redolog记录这个过程看似相同但其实有很大的差别 在事务中我们的操作大多都是随机操作各个数据页的这其中涉及到了大量的随即磁盘IO很耗费性能而log日志时顺序记录的即顺序磁盘IO这两者之间相差了很大的性能 这种机制叫做WAL(Write-Ahead Logging)
因为脏页早晚都会正常写入所以log里就会有很多无用的日志这时候就需要定时清理两个log文件循环记录
Undo Log 解决事务原子性
undo log回滚日志用于记录数据被修改前的信息作用有两个提供回滚和MVCC
undolog 和redolog记录物理日志不一样他记录的是逻辑日志 比如我写了一条delete删除id为1的数据那么undolog记录的则是相反的插入一条id为1的数据数据的内容就是删除的内容 比如我写了一条update 把id为2的姓名从李四改成张三那么undolog记录的就是 update - 把id为2的人的姓名改成李四
当执行rollback时就直接调用对应的undolog从而实现了内容的回滚。
Undo log销毁undo log 在事务执行时产生事务提交时并不会立即删除undolog因为这些日志还可能会用在MVCC中 Undo log存储undo log采用段的方式进行管理和记录存放在rollback segment回滚段中其中包含了1024个undo log segment
MVCC
当前读读取的是记录的最新版本读取时还要保证其他并发事务不能修改当前记录会对读取的记录进行加锁 比如select lock in share modeinsertdelete
快照读读取的是记录数据的可见版本有可能是历史数据不加锁是非阻塞读 Read Committed每次select 都生成一个快照都 Repeatable Read开启事务后第一个select语句才是快照读的地方 Serializable快照读都会退化为当前读
MVCC 全程Multi-Version Concurrency Control 多版本并发控制指维护一个数据的多个版本是的读写操作没有冲突快照都为MySQL实现MVCC提供了一个非阻塞读的功能
MVCC的具体实现还需要依赖于数据库记录的三个隐式字段undologreadView
MVCC实现原理
记录当中的隐藏字段 DB_TRX_ID: 最近修改十五ID记录插入这条记录或最后一次修改该记录的事务ID DB_ROLL_PTR:回滚指针指向这条记录的上一个版本用于配合undo log 指向下一个版本 DB_ROLL_ID: 隐藏主键如果表结构没有指定主键将会生成该隐藏字段
看表结构的方法 ibd2sdi xx.ibd;当然也可以用navicat直接看
undo log版本链
不同或相同事务对同一条数据进行修改会导致该记录的undolog生成一条记录版本链表链表的头部是最新的旧记录尾部是最早的旧记录
而具体要返回哪个版本需要有readview决定 readview 读视图是快照读sql执行时MVCC提取数据的依据记录并维护系统当前活跃的事务(也就是未提交的事务)id
readview有四个核心字段 m_ids: 当前活跃的事务ID集合 min_trx_id: 最小活跃事务ID max_trx_id: 预分配事务ID也就是当前最大事务ID1 creator_trx_id: ReadView创建者的事务ID
版本链数据访问规则 我们令当前事务ID为trx_id
trx_id creator_trx_id ? 可以访问该版本 - 成立则说明数据是这个事务更改的trx_id min_trx_id ? 可以访问该版本 - 成立则说明该数据已经提交过了trx_id max_trx_id ? 不可以访问该版本 - 成立则说明该事务时在readview生成之后才开启的min_trx_id trx_id max_trx_id ? 如果trx_id不在m_ids中是可以访问该版本的 - 成立则说明数据已经提交了
不同隔离级别生成readview的实际不同
读已提交在事务中每次执行快照读时生成readview
可重复读仅在事务中第一次执行快照读时生成readview后续复用该readview
用readview生成后得到的四个核心字段带入到上面的判断是否能访问的公式中然后从undolog版本链由上到下依次寻找那个版本符合就可以访问哪个版本
这就是MVCC在快照读的时候决定使用哪个版本 而MVCC加上锁就保证了数据的隔离性
而一致性是由redo log 和 undo log共同保证的