数据库2

目录

MySQL的体系结构

MySQL表存储引擎

InnoDB体系架构

关键特性

启动,关闭与恢复

文件

索引与算法

事务

备份与恢复

性能调优


数据库:物理操作系统文件或其他形式文件类型的集合

数据库实例:由数据库后台进程/线程以及一个共享内存区域组成,共享内存可以被运行后台进程/线程所共享,数据库实例才是真正用来操作数据库文件的。

MySQL被设计成一个单进程多线程架构的数据库,实例和数据库的关系是一一对应的,但是在集群情况下可能存在一个数据库可被多个实例使用的情况。

MySQL的体系结构

  • 连接池组件。
  • 管理服务和工具组件。
  • SQL接口组件。
  • 查询分析器组件。
  • 优化器组件。
  • 缓冲组件。
  • 插件式存储引擎。
  • 物理文件。

MySQL表存储引擎

  • InnoDB存储引擎:

主要面向在线实物处理方面的应用,特点是行锁设计,支持外键,并支持非锁定读即默认情况下不会产生锁。

InnoDB通过使用多版本并发控制(MVCC)来获得高并发性,并且实现了SQL标准的4种隔离级别,默认为REPEATABLE级别,同时使用一种被称为next-key locking的策略来避免幻读现象的产生,提供了插入缓冲,二次写,自适应哈希索引,预读等高性能和高可用功能。

对于表中数据存储,innoDB存储引擎采用了聚集的方式,每张表的存储都按主键的顺序存放,如果没有显示地在表定义时置顶主键,InnoDB存储引擎会为每一行生成一个6字节的ROWID,并以此作为主键。

  • MyISAM存储引擎:
  • NDB存储引擎:
  • Memory存储引擎:
  • Archive存储引擎:
  • Federated存储引擎:
  • Maria存储引擎:

InnoDB体系架构

  • 后台线程:

作用负责刷新内存池中的数据,保证缓冲池中的内存缓存的最近的数据,此外,将已修改的数据文件刷新到磁盘文件,同时保证在数据库发生异常情况下InnoDB能恢复到正常运行状态。

默认情况下,InnoDB存储引擎的后台线程有7个,4个IOThread,1个master thread,1个锁(lock)监控线程,1个错误监控线程,IO thread的数量由配置文件中的innodb_file_io_thread参数控制,默认为4;分别是insert buffer thread,log thread,read thread,write thread,Linux下不可以调整

  • 内存

InnoDB存储引擎内存由以下几个部分构成,缓冲池,重做日志缓冲池以及额外内存池,分别由配置文件中的参数innodb_buffer_pool_size和innodb_log_buffer_size的大小决定,

缓冲池是占最大快内存的部分,用来存放各种数据的缓存,因为InnoDB存储引擎的工作方式是将数据库文件按页(16K)读取到缓冲池,然后按最近最少使用(LRU)算法来保留在缓冲池中的缓存数据,如果要修改总是先修改缓冲池中的页,(发生修改后,页即为脏页),然后在按照一定的频率将缓冲池的脏页刷新到文件。

缓存池中缓存的数据页类型有:索引页,数据页,undo页,插入缓冲,自适应哈希索引,InnoDB存储的锁信息,数据字典信息等。

  • master thread

InnoDB存储引擎的主要工作都是在一个单独的后台线程master thread中完成的。

master thread的线程优先级最高,内部由几个循环组成:主循环loop,后台循环backgroud loop,刷新循环flush loop,暂停循环suspend loop,master thread会根据数据库运行状态在这几个循环中进行切换。

主循环由两大部分操作:每秒钟的操作和每十秒的操作,每一秒的操作包括,日志缓冲刷新到磁盘,即使这个事务还没有提交(总是),合并插入缓冲(可能),至多刷新100个InnoDB的缓冲池中的脏页到磁盘(可能),如果当前没有用户活动,切换到后台循环(可能)。即使某个事务还没提交,InnoDB存储引擎仍然会每秒重做日志缓冲中的内容刷新到重做日志文件,这可以解释为什么在打的事务commit的时间是很快的。

合并插入缓冲并不是每秒都发生,存储引擎会判断当前一秒内发生的IO次数是否小于5次,如果小于5次,InnoDB认为当前IO压力小,可以执行合并插入缓冲的操作,同样刷新100个脏页也不是每秒发生,存储引擎通过判断当前缓冲池中的脏页比例是否超过了innodb_max_dirty_pages_pct这个参数(默认90,代表90%)如果超过了这个阈值存储引擎认为需要做磁盘同步操作。

每10秒的操作:刷新100个脏页到磁盘(可能),合并至多5个插入到缓冲,将日志缓冲刷新到磁盘,删除无用的Undo页,刷新100个或者10个脏页到磁盘,产生一个检查点(总是)

后台循环:若当前没有用户活动(数据库空闲时)或者数据库关闭时,就会切换到这个循环,执行以下操作,删除无用的Undo页,合并20个插入缓冲,跳回到主循环(总是),不断刷新100个页,直到符合条件(可能,跳转到刷新循环中完成),如果刷新循环中页没有什么事情可以做了,InnoDB存储引擎会切换到暂停循环,将主线程挂起,等待事件发生,若启用了InnoDB存储引擎,却没有使用任何存储引擎的表,那么master thread 总是处于挂起状态。

master thread的潜在问题:InnoDB存储引擎对于IO是有限制的,在缓冲池向磁盘刷新时其实都做了一定的硬性规定(1秒钟内处理100个页的写入和20个插入缓冲的合并),解决通过修改参数,

关键特性

InnoDB存储引擎的关键特性包括插入缓冲,两次写,自适应哈希索引,这些特性为InnoDB存储引擎带来了更好的性能和更高的可靠性。

插入缓冲:插入缓冲的使用需要满足两个条件,索引是辅助索引,索引不是唯一的。满足这两个的时候回使用插入缓冲来提高性能,

两次写:插入缓冲带来的是性能,两次写带来的是可靠性,当数据库宕机时,可能发生数据库正在写一个页面,而这个页面只写了一部分的情况,称之为部分写失效,两次写有两部分组成,一部分是内存中的doublewrite buffer,大小为2M,另一部分是磁盘上共享表空间中连续的128个页,即两个区,大小同样为2M,当缓冲池的脏页刷新时,并不直接写磁盘,而是会通过memcpy函数将脏页先拷贝到内存中的dublewrite buffer,之后通过dublewrite buffer在分两次,每次写入1M到共享表空间的物理磁盘上,然后马上调整fsync函数,同步磁盘,避免缓冲写带来的问题,如果操作系统在将页写入磁盘的过程中崩溃了,在恢复的过程中,存储引擎可以从表空间中的doublewrite buffer中找到改页的一个副本,将其拷贝到表空间文件,在应用重做日志。

自适应哈希索引:存储引擎会监控对表上索引的查找,如果观察到建立哈希索引可以带来速度的提升,则建立哈希索引,所以称之为自适应的,自适应哈希通过缓冲池的B+树构造而来,因此建立的速度快,而且不需要讲整个表都建立哈希索引。

启动,关闭与恢复

文件

  • 参数文件:告诉MySQL实例启动时在哪里可以找到数据库文件,并且制定初始化参数类型等
  • 日志文件:

错误日志(对MySQL的启动运行,关闭的过程进行记录),

慢查询日志(默认情况下不启动慢查询日志,默认值为10秒,超过10秒的查询语句进行记录,等于不会),

查询日志(记录了所有对MySQL数据库请求的信息),

二进制日志(记录了对数据库执行更改的所有操作,但是不包括select和show操作,作用:恢复,复制。当使用事务的表存储引擎时,所有未提交的二进制日志hi被记录到一个缓寸中,等该事务提交时直接将缓冲中的二进制日志写入二进制文件)

  • socket文件:当Unix域套字进行连接时需要的文件。
  • pid文件:MySQL实例的进程ID文件。
  • MySQL表结构文件:
  • 存储引擎文件:

InnoDB存储引擎表类型:在InnoDB存储引擎表中,每张表都有一个主键,如果创建表的时候没有显式的定义主键,会按如下的方式选择或者创建主键,首先表中是否有非空的唯一索引,有即为主键,不符合上诉条件,会自动创建一个6字节大小的指针。

  • InnoDB逻辑存储结构:

所有数据都存放在表空间,表空间又由段,区,页,组成。

表空间:是存储引擎的最高层,每张表空间内存放的只是数据,索引和插入缓冲,其他类数据如撤销信息,系统事务信息,二次写缓冲等还是存放在原来的共享表空间内,

段:常见的有数据段,索引段,回滚段等,InnoDB存储引擎表是索引组织的,因此数据即索引,索引即数据,那么数据段即为B+树的页节点,索引段即为B+树的非索引节点。不是每个对象都有段,表空间是由分散的页和段组成。

区:区是由连续的64个连续页组成,每个页大小为16K,即每个区的大小为1M,对于大的数据段,最多每次可以申请4个区,保证数据的顺序性能。

页:页也叫做块,是InnoDB磁盘管理的最小单位,常见的页类型有,数据页,Undo页,系统页,事务数据页,插入缓冲位图页,插入缓冲空闲列表页,未压缩的二进制大对象页,压缩的二进制大对象页。

行:每页最多允许存放16KB/2~200行的记录,即7992行记录。

  • InnoDB物理存储结构

InnoDB表由共享表空间,日志文件组,表结构定义文件组成,

  • InnoDB行记录格式

2种情况

  • InnoDB数据页结构

数据页由以下7个部分构成,文件头,页头,Infimun+Supermum Recods,用户记录即行记录,空闲空间,页目录,文件结尾信息。

  • Named File Formats
  • 约束

数据完整性有三种形式:实体完整性(保证表中有一个主键),域完整性(保证数据的值满足特定条件,外键约束,编写触发器,DEFAULT约束),参照完整性(保证两张表之间的关系)

提供的约束:Primary Key ,Unique Key ,Foreign key,Default,Not null。

约束的创建与查找:约束的建立可以在建表的时候进行定义,也可以之后用alter table命令来创建。

约束和索引的区别:约束是一个逻辑的概念,用来保证数据的完整性,索引是一个数据结构,有逻辑上的概念,在数据库中更是一个物理存储的方式。

触发器约束:触发器的作用是在insert delete和update命令之前或之后自动调用SQL命令或者存储过程。(防止非法数据,例如减负值)

外键:外键用来保证参照完整性,MySQL默认的MyISAM存储引擎并不支持外键,对于外键的定义只起到一个注释的 作用,InnoDB存储引擎则完全支持外键约束,

  • 视图

视图是一个命名的虚表,他由一个查询来定义,可以当做表使用,与持久表不同的是,他没有物理表现形式。

作用:被用作一个抽象装置,特别是对于一些应用程序,程序本身不需要关心基表的结构,只需要按照视图定义来获取数据或更新数据,在一定程度上起到一个安全层的作用。

  • 分区表

MySQL数据库支持的分区类型为水平分区(指同一表中不同的行记录分配到不同的物理文件中),并不支持垂直分区(指将同一表中不同的列分配到不同的物理文件),此外MySQL数据库的分区是局部分区索引,一个分区中即存放了数据又存放了索引。 

分区主要用于高可用性,利于数据库管理,如果表中存在主键或者是唯一索引时,分区列必须是唯一索引的一个组成部分。

对于查删,可以直接定位分区,加快某些查询操作

RANGE分区,优化器只能对YEAR(),To_DAYS(),TO_SECONDS(),UNIX_TIMESTAMP()。

LIST分区,分区列的值是离散的,而非连续的。插入的值不在分区的定义中,MySQL数据库会抛出异常。多个插入的过程中分区未定义值时,MyISAM和InnoDB存储引擎的处理完全不同,MyISAM引擎会将之前的插入,InnoDB存储引擎将其视为一个事务,因此没有数据插入。

HASH分区:目的是将数据均匀地分布到预先定义的各个分区中,保证各分区的数据数量大致都是一样的。

Key分区:和hash分区相似,hash分区使用用户定义的函数进行分区,key分区使用MySQL数据库提供的函数进行分区。

columns分区:前4个分区,条件必须是整形,而columns分区可以直接使用非整形的数据进行分区。

子分区:在分区的基础上在进行分区,也叫复合分区,应该注意以下问题,每个子分区的数量必须相同,如果在一个分区表上的任何分区上使用SUBPARTITION来明确定义任何子分区,那么就必须定义所有的子分区,每个SUBPARTITION子句必须包括子分区的一个名称。在每个分区内,子分区的名称必须是唯一的

分区中的NULL值:MySQL数据库允许对null值做分区,MySQL数据库分区总是把Null值视为小于任何一个非NULL值,这和MySQL数据库中对于null的order by的排序是一样的,对于不同的分区类型,MySQL数据库对于null值的处理是不一样的。对于RANGE分区如果对于分区插入了NULL值,则会将改值放入最左边的分区。LIST分区下要使用NULL值则必须指出放入那个分区,否则报错,HASH和KEY分区对于NULL的处理方式,和RANGE分区,LIST不一样,任何分区函数都会将含有null值的记录返回为0

分区和性能:数据库应用分两类,一类是OLTP(在线事务处理),一类是OLAP(在线分析处理)对于OLAP应用分区的确可以很好的提高查询性能,因为OLAP应用的大多数查询需要频繁的扫描一张很大的表,对于OLTP的应用,分区应该很小心,大部分都是通过索引返回几条数据即可,而根据B+数索引的原理可知,对一张达标,一般B+树需要2~3次磁盘IO,因此B+树可以很好的完成操作不需要分区帮助

索引与算法

  • InnoDB存储引擎索引概述

InnoDB存储引擎支持两种常见的索引,一种是B+树索引,一种是哈希索引,InnoDB支持的哈希索引是自适应的,会根据表的使用情况自动为表生成哈希索引,不能人为干预是否在一张表中生成哈希索引。

B+树索引就是传统意义上的索引,是最常用有效的索引,B+树索引的构造类似于二叉树,根据键值快速找到数据,B+树索引并不能找到一个给定键值的具体行,B+树索引能找到的只是数据行所在的页,然后数据库通过把页读入内存,在在内存中进行查找,最后得到数据。

  • 二分查找法
  • 平衡二叉树
  • B+树
  • B+ 树索引

B+树索引本质就是B+树在数据库中的实现,B+索引在数据库中有一个特点就是高扇出性,因此在数据库中B+树的高度一般都在2~3层,也就是查找某一键值的行记录最多需要2到3次IO,(一般磁盘每秒可以做100次IO,意味着查询只需0.02-0.03秒)

数据库中的B+树索引可以分为聚集索引和辅助聚集索引,区别是叶节点是否是一整行的信息。

聚集索引:按照每张表的主键构造一颗B+树,并且叶节点中存放着整张表的行记录数据,因此也让聚集索引的叶节点成为数据页,每个数据页都通过一个双向链表来进行链接和B+树数据结构一样。由于实际的数据页只能按照一颗B+树进行排序,因此每张表只能拥有一个聚集索引,在许多情况下,查询优化器飞船倾向采用聚集索引,因为能在叶节点上找到数据,能够快速发现某一段范围的数据页需要扫描。

聚集索引并不是物理存储上的连续,是逻辑上的连续的,页是通过双向链表链接,页按照主键的顺序排列,每个页中的记录也是通过双向链表进行维护,物理存储上可以同样不按照主键存储。

聚集索引的另一个好处是对于主键的排序查找和范围查找速度非常快,叶节点的数据就是我们需要查询的数据。

辅助索引,叶级别不包含行的全部数据,叶节点除了包含键值以外,每个叶级别中的索引行还包含了一个书签,改书签用来告诉InnoDB存储引擎,哪里可以找到与索引对应的行数据。

辅助索引并不影响数据在聚集索引中的组织,因此每张表上可以有多个辅助索引,当通关辅助索引来查找数据是,InnoDB存储引擎会遍历辅助索引并通过叶级别的指针获得执行主键索引的主键,然后通过主键索引来找到一个完整的行记录。

B+树索引的管理:索引的创建删除可以通过两种方法,alter table,create/drop index

InnoDB存储引擎支持一种快速索引创建方法,当然这种方法直限定于辅助索引,对于主键的创建和删除还是需要重新建一张表,对于辅助索引的创建,InnoDB存储引擎会对表加上一个S锁,因此在创建的过程中只能进行读操作,删除辅助索引只需在InnoDB存储引擎的内部视图更新下,将辅助索引的空间标记为可用,并删除MySQL内部视图上对该表的索引定义即可。

查看索引信息可用使用show index语句。

  • B+树索引的使用

什么时候使用B+索引:当一个字段取值范围广,几乎没有重复即高选择性,B+索引是最适合的,MySQL数据库的优化器会通过EXPLAN的rows字段预估查询可能得到的行,如果大于某一个值,B+树会选择扫描全表,至于这个值一般在20%,超过表中20%优化器就不会使用索引,而去全表扫描

顺序读,随机读与预读取:索引的使用原则即高选择,取出少部分数据,顺序读是指顺序的读取磁盘上的块,随机读是指访问的块不是连续的,需要磁盘的磁头不断移动,顺序读是指索引的叶节点数据能顺序地读取所需的行数据,这个顺序只是逻辑的读,磁盘上可能还是随机的,但是相对还是顺序的,因为根据区来管理的,区是64个连续页,随机读是指访问辅助索引叶节点不能完全得到结果,需要根据辅助索引叶节点中的主键去找实际行数据,性能低于顺序读,因此优化器才会选全表扫描。

为了提高读取的性能,InnoDB存储引擎引入了预读取技术,是指通过一次IO请求将多个页预读取到缓冲池中,并且估计预读取的多个页马上会被访问,传统的IO请求每次只会读一个页,预读取技术可以大大提高读取性能。

InnoDB存储引擎有两个预读方法,称为随机预读取和线性预读取,随机预读取由于性能不高甚至拉低呗取消,线性依然保留当一个区的多少页(可配置)被顺序访问时,则预读下一个区的所有页。

辅助索引的优化使用:

联合索引:指对表上的多个列做索引,本质上还是一个B+树,不同的是键值的数量不是1,而是大于等于2

  • 哈希算法

InnoDB存储引擎中自适应哈希索引使用的是散列表的数据结构。

哈希表:也叫散列表,直接寻址表改进而来,

InnoDB存储引擎中的哈希算法:使用哈希算法对字典进行查找,其冲突机制采用链表方式,哈希函数采用除法散列方式,

自适应哈希索引:哈希索引只能用来搜索等值的查询,where a="",而对于其他查找类型,如范围查找,是不能使用哈希索引的

数据库系统使用锁为了支持对共享资源进行并发访问,提供数据的完整性和一致性。

  • InnoDB存储引擎中的锁

锁类型: 

InnoDB存储引擎实现了两种标准的行级锁:共享锁Slock,允许事务读一行数据,排他锁Xlock,允许事务删除或更新一行数据。当一个事务已经获得了共享锁,那么另外的事务可以立即获得行的共享锁,因为读取没有改变行的数据,这种情况称为锁兼容,但如果有事务想获得行的排他锁,则必须等待事务释放行上的共享锁,这种情况称为锁不兼容。

InnoDB存储引擎支持两种意向锁:意向共享锁ISLock,事务想要获得一个表中某几行的共享锁,意向排他锁IXLock,事务想获取一个表中某几行的排他锁,因为InnoDB存储引擎支持的是行级锁,所以意向锁其实不会阻塞全表扫描以外的任何请求。

一致性的非锁定读:是指InnoDB存储引擎通过行多版本控制的方式来读取当前执行时间数据库中行的数据,如果读取的行正在执行Delete,update操作,这时读取操作不会因此等待行上锁的释放,相反InnoDB存储引擎会去读取行的一个快照数据。该实现是通过Undo段来实现,而Undo用来在事务中回滚数据,因此快照数据本身是没有额外的开销,读取快照数据页不需要上锁,因为没有必要对历史数据进行修改。非锁定读的机制大大提高了数据读取的并发性,在InnoDB存储引擎默认的设置下,这是默认的读取方式,读取不会占用和等待表上的锁,但是在不同事务隔离级别下,读取的方式不同,并不是每个事务隔离级别下的读取都是一致性读,

即使都是使用一致性读,但是对于快照数据的定义也是不相同。快照数据其实就是当前行数据之前的历史版本,可能有多可版本,一个行可能不止有一个快照数据,我们称这种技术为行多版本技术,由此带来的并发控制称之为多版本并发控制MVCC(https://blog.csdn.net/u013007900/article/details/78641913

select语句的加锁操作:支持两种操作,select…for update,对读取的行记录加一个X锁,其他事务想在这些行上加任何锁都会被阻塞,select…lock in share mode对读取的行记录加一个S锁,其他事务可以向呗锁定的记录加S锁,但是对于加X锁,则会阻塞。对于一致性非锁定读,即使行已经使用select…for update 也是可以进行读取的,另外for update ,lock in share mode必须在一个事务中,当事务提交锁页释放。

自增长和锁:在InnoDB存储引擎中,对每一个含有自增长的表都有一个自增长计数器,当对含有自增长计数器的表进行插入操作时,这个计数器会被初始化,插入操作会依据这个自增长的计数器值加一赋予自增长列,这个实现方式称作auto-inc locking,这种锁采用一种特殊的表锁机制,为了提高插入性能,锁不是在一个事务完成后释放,而是在完成对自增长值插入的SQL语句后立即释放,对于自增长的并发插入较差必须等待前一个插入完成对于insert…select的大数据量插入会影响插入性能,因为另一个事务插入会阻塞,InnoDB存储引擎提供了一种轻量级互斥量的自增长实现机制,提高自增长值插入性能。InnoDB存储引擎下,自增长值的列必须是索引,并且是索引 的第一个列。第二个会报错,MyISAM则没有问题。(https://blog.csdn.net/zheng0518/article/details/76302167

外键和锁:外键主要用于引用完整性的约束检查,在InnoDB存储引擎中,对于一个外键列,如果没有显式地对这个列加索引,InnoDB存储引擎会自动的为其加一个索引,对于外键值的插入或者更新,首先需要查询父表中的记录,不是使用一致性非锁定读的方式,会使用lock in share mode方式,主动对父表价格S锁,如果此时父表上已经加X锁,那么子表会阻塞。

锁的算法:InnoDB存储引擎有3种行锁的算法设计分别是,record lock:单个行记录上的锁。gap lock:间隙锁,锁定一个范围,但不包含记录本身。net-key lock:gap lock+record lock,锁定一个范围,并且锁定记录本身。

record lock 总是会去锁住索引记录,如果InnoDB存储引擎表建立的时候没有设置任何一个索引,InnoDB存储引擎会使用隐式主键来进行锁定。

net-key lock是结合了gap lock,record lock的一种锁定算法,在合格算法下InnoDB对于行的查询都是采用这种锁定算法,对于不同的SQL查询语句,可能设置共享的next-key lock 和排他的next-key lock。

在事务隔离级别为repeatable read模式下,next-key lock算法是默认行记录锁定算法。

锁问题:

锁可以实现事务的隔离性的要求,使得事务可以并发的工作,锁提高了并发,但是却会带来问题,不过因为事务隔离性的要求,锁只会带来3种问题,如果可以防止将不会产生异常。

 

 

丢失更新:当出现下面情况时,会发生丢失更新

  1. 事务T1查询一行数据,放入本地内存,并显示给一个终端用户user1.

  2. 事务T2也查询该行数据,并将取得的数据显示给终端用户user2.

  3. user1修改了这行记录,更新数据库并提交。

  4. user2修改了这行记录,更新数据库并提交。

显然这个过程中user1的修改更新操作丢失了,避免丢失更新的发生,其实需要让这种情况下的事务变成串行操作,而不是并发的操作,即在第一种情况下对用户读取的记录加上一个排他锁,同样发生第二种情况时也加上一个排他锁,这种情况下,第二步就必须等待1,3完成,最后完成第4步。

脏读:脏数据和脏页有所不同,脏页指的是在缓冲池中已经被修改的页,但是还没有刷新到磁盘,即数据库实例内存中的页和磁盘的页中的数据是不一致的,当然在刷新到磁盘之前,日志都已经写入了重做日志文件中,而所谓的脏数据是指在缓冲池中呗修改的数据,并且还没有被提交。脏读指的就是在不同的事务下,可以读到另外事务未提交的 数据,简单说就是可以读到脏数据。

不可重复读:是指在一个事务内多次读同一数据,在这个事务还没结束时,另一个事务也访问该同一数据,那么在第一个事务的两次读取之间,由于第二个事务修改,第一个事务读取的数据可能是不一样的,称作不可重复读。

不可重复读和脏读的区别是,脏读是读到没提交的数据,不可重复读是读到是已提交的数据,

通过next-key lock算法来避免不可重复读问题,在next-key lock算法下,对于索引的扫描,不仅仅是锁住扫描到的索引,而且还锁住了这些索引覆盖的范围(gap),因此对于这个范围内的插入都是不允许的,这样避免了另外的事务在这个范围插入数据导致不可重复读的问题。

阻塞:

因为不同锁之间的兼容性关系,所以在有些时刻,一个事务中的锁需要等待另一个事务中的锁释放他所占有的资源,在InnoDB存储引擎中,用mutex数据结构来实现锁,当另一个事务就会发生等待阻塞,默认50秒可以设置超时时间和是否进行回滚。

默认情况下InnoDB存储引擎不会回滚超时引发的错误异常,死锁除外

死锁:

如果程序是串行的,那么不会发生死锁,InnoDB存储引擎后台有一个锁监控线程,该线程负责查看死锁问题,并告知用户。发现死锁后,InnoDB存储引擎会马上回滚一个事务

锁升级:

将当前锁的粒度降低,把一个表的1000个行锁升级也页锁,或者将页锁升级为表锁,为了避免锁的开销,会频繁出现锁升级现象。

server数据库的锁升级

一句单独的SQL语句在一个对象上持有的锁数量超过了阈值,默认5000,如果不同对象的话,则不会发生锁升级

锁资源占用内存超过了激活内存的40%时,就会发生锁升级。

锁升级带来的问题是锁颗粒度降低导致并发性能降低

InnoDB存储引擎不存在锁升级的问题,在InnoDB存储引擎中,没有锁开销。

事务

InnoDB存储引擎中的事务完全符合ACID的特性(原子性,一致性,隔离性(事务间不可见,通过锁实现),持久性)

事务的实现:

隔离性通过锁实现,原子性,一致性,持久性通过数据库的redo和undo来完成。

redo:InnoDB存储引擎中事务日志通过重做(redo)日志文件和InnoDB存储引擎的日志缓冲来实现,当事务执行时,会往InnoDB存储引擎的日志缓冲里插入事务日志,当事务提交时,必须将InnoDB存储引擎的日志缓冲写入磁盘,也就是在写数据前先写日志,这种方式称为预写日志方式。

InnoDB通过预写日志的方式来保证事务的完整性,这意味着磁盘上存储的数据页和内存缓冲池中的页是不同步的,对于内存缓冲池中的页的修改,先是写入重做日志文件,然后写入磁盘,

undo:重做日志记录了事务的行为,但是事务有时还需要撤销,这时就需要undo,undo和redo正好相反,对数据库进行修改时,数据库不但会产生redo而且还会产生一定量的undo,即使事务语句失败了,或者回滚,就可以利用这些undo信息将数据回滚到修改之前的样子,与redo不同的是,redo存放在重做日志中,undo存放在数据库内部的一个特殊段中,叫做undo段,undo段位于共享表空间内,undo只是逻辑的恢复到原来的样子,表空间的大小不会因为多insert而收缩

事务控制语句:

在MySQL命令行的默认设置下,事务是自动提交的,

事务隔离级别:4种

分布式事务:XA,JTA

不好的事务习惯:

  1. 在循环中提交,因为每一次提交都需要写一次重做日志。
  2. 使用自动提交,
  3. 使用自动回滚

备份与恢复

……

性能调优

  1. 选择合适的CPU。
  2. 内存的重要性。
  3. 硬盘对数据库性能的影响。
  4. 合理地设置RAID。
  5. 操作系统的选择也重要。
  6. 不同文件系统对数据库的影响。
  7. 选择合适的基准测试工具。

选择合适的CPU:

数据库一般分为两类,OLTP(在线事务处理,多用于数据仓库或数据集市中,一般需要执行复杂的SQL语句来进行查询)和OLAP(在线分析处理,)

 

 

 

 

 

MySQL技术内幕InnoDB存储引擎

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值