MySQL的架构

1、MySQL逻辑架构数据库

前言:为了充分发挥MySQL的性能并顺利地使用,就必须理解其设计缓存

 

MySQL最重要、最不同凡响的特性是它的存储引擎架构,这种架构的设计将查询处理及其余系统任务和数据的存储/提取相分离。因此这种处理和存储分离的设计能够在使用时根据性能、特性,以及其余需求来选择数据存储的方式安全

 

一、MySQL的逻辑架构图服务器

1.一、链接管理与安全性架构

1.二、优化与执行并发

 

二、并发控制函数

2.一、读写锁高并发

  共享锁(读锁)、排他锁(写锁)工具

2.二、锁粒度性能

  表锁、行级锁

 

三、事务

3.一、 ACID

3.二、隔离级别

  未提交读(脏读)  事务能够读取未提交的数据,性能不比其余级别好太多,如非必要通常不使用

  提交读(不可重复读)  一个事务从开始直到提交以前,所做的任何修改对其余事务都是不可见的  

  可重复读(MySQL的默认事务隔离级别)  解决了脏读问题,保证了在同一个事务中屡次读取一样记录的结果是一致的。但可重复读会出现幻读问题,当一个事务在读取某个范围内的记录时,另一个事务又在该范围内插入了新的记录,这时当以前的事务再去读取该范围的记录时,就产生了幻行

  可串行化(最高隔离级别)  强制事务串行执行,避免了幻读的问题,在读取的每一行数据上都加锁,因此可能致使大量的超时和锁争用的问题。只有在很是须要确保数据的一致性并且能够接受没有并发的状况下,才考虑采用该级别

3.三、死锁

  死锁是指两个或者多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而致使恶性循环的现象

  为了解决这种问题,数据库系统实现了各类死锁检测和死锁超时机制。InnoDB目前处理死锁的方式是,将持有最少行级排他锁的事务进行回滚

  锁的行为和顺序是和存储引擎相关的。死锁发生之后,只有部分或者彻底回滚其中一个事务,才能打破死锁。因此应用程序在设计时必须考虑如何处理死锁,大多数状况下只需从新执行因死锁回滚的事务便可。

3.四、事务日志

  事务日志能够帮助提升事务的效率。

  使用事务日志,存储引擎在修改表的数据时只须要修改其内存拷贝,再把该修改行为 记录到 持久在硬盘上的事务日志中,而不用每次都将修改的数据自己持久到磁盘。

  事务日志采用的是追加的方式,所以写日志的操做是磁盘上一小块区域内的顺序I/O,而不像随机I/O须要在磁盘的多个地方移动磁头,因此采用事务日志的方式相对来讲要快得多

  在事务日志持久之后,内存中被修改的数据在后台能够慢慢地刷回到磁盘。一般称为预写式日志,全部其实修改数据须要写两次磁盘(一次是事务日志持久化到磁盘,一次是修改数据刷回到磁盘)

3.五、MySQL中的事务

  MySQL提供了两种事务型的存储引擎:InnoDB和NDB Cluster。另外还有一些第三方存储引擎也支持事务,比较知名的包括XtraDB和PBXT

  MySQL默认采用自动提交模式。若是不是显式地开始一个事务,则每一个查询都被看成一个事务执行提交操做。

 

四、多版本并发控制

  MySQL的大多数事务型存储引擎实现的都不是简单的行级锁。基于提高并发性能的考虑,它们通常都同时实现了多版本并发控制(MVCC)

  MVCC的实现,是经过保存数据在某个时间点的快照来实现的。也就是说,无论须要执行多长时间,每一个事务看到的数据都是一致的。由于事实上根据事务开始的时间不一样,每一个事务对同一张表,同一时刻看到的数据多是不同的

  不一样存储引擎的MVCC实现是不一样的,典型的有乐观(optimistic)并发控制和悲观(pessimistic)并发控制。

  悲观锁的理解:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操做。悲观锁的实现,每每依靠底层提供的锁机制;悲观锁会致使其它全部须要锁的线程挂起,等待持有锁的线程释放锁。

  乐观锁的理解:假设不会发生并发冲突,每次不加锁而是假设没有冲突而去完成某项操做,只在提交操做时检查是否违反数据完整性。缺点是不能解决脏读的问题,因此一般乐观锁与提交读的隔离等级共同使用。

  InnoDB的MVCC,是经过在每行记录后面保存两个隐藏的列来实现的。这两个列,一个保存了行的建立时间,一个保存行的过时时间(或删除时间),实际上存储的不是实际的时间值,而是系统版本号。每开始一个新事务,系统版本号都会自动递增。事务开始时刻的系统版本号会做为事务的版本号,用来和查询到的每行记录的版本号进行比较。

  以可重复读(REPEATABLE READ)隔离级别为例,解析MVCC具体如何操做:

  SELECT

    InnoDB会根据如下两个条件检查每行记录:

    一、只查找版本早于当前事务版本的数据行(行的系统版本号小于或等于事务的系统版本号),确保事务读取的行,要么是在事务开始前已经存在,要么是事务自身插入或者修改过

    二、行的删除版本要么未定义,要么大于当前事务版本号,确保事务读取到的行,在事务开始以前未被删除。

    只有符合这两个条件的记录,才能返回做为查询结果

  INSERT

    为新插入的每一行保存当前系统版本号做为行版本号

  DELETE

    为删除的每一行保存当前系统版本号做为行删除标识

  UPDATE

    为插入一行新记录,保存当前系统版本号做为行版本号,同时保存当前系统版本号到原来的行做为行删除标识

  优缺点:保存两个额外系统版本号,使大多数读操做均可以不用加锁。使读数据操做很简单,性能很好。不足之处是每行记录都须要额外的存储空间,须要作更多的行检查工做,以及一些额外的维护工做

  MVCC只在可重复读和提交读两个隔离级别下工做。由于未提交读老是读取最新的数据行,而不是符合当前事务版本的数据行。而可串行化则会对全部读取的行都加锁。

 

五、MySQL的存储引擎

  在文件系统中,MySQL将每一个数据库保存为数据目录下的一个子目录。建立表时,MySQL会在数据库子目录下建立一个和表同名的.frm文件保存表的定义。由于MySQL使用文件系统的目录和文件来保存数据库和表的定义,大小写敏感性和具体的平台密切相关。

  不一样的存储引擎保存数据和索引的方式是不一样的,但表的定义则是在MySQL服务层统一处理。

5.一、InnoDB存储引擎

  InnoDB是MySQL的默认事务型引擎,也是最重要、使用最普遍的存储引擎。

  InnoDB的性能和自动崩溃恢复特性,使得它在非事务型存储的需求中也很流行。

  InnoDB的数据存储在表空间中,表空间是由InnoDB管理的一个黑盒子,由一系列的数据文件组成。

  InnoDB采用MVCC来支持高并发,并实现了四个标准的隔离等级。其默认级别是可重复读,而且经过间隙锁策略防止幻读的出现。间隙锁使得InnoDB不只仅锁定查询涉及的行,还会对索引中的间隙进行锁定,以防止幻影行的插入。

  InnoDB表是基于聚簇索引创建的。聚簇索引对主键查询有很高的性能,不过它的二级索引(非主键索引)中必须包含主键列,因此若是主键列很大的话,其余的全部索引都会很大。所以,若表上的索引较多的话,主键应当尽量的小。

  InnoDB内部作了不少优化,包括从磁盘读取数据时采用的可预测性预读,可以自动在内存中建立hash索引以加速读操做的自适应哈希索引,以及可以加速插入操做的插入缓冲区等。

  做为事务型的存储引擎,InnoDB经过一些机制和工具支持真正的热备份,MySQL的其余存储引擎不支持热备份。

 5.二、MyISAM存储引擎

  在MySQL 5.1及以前的版本,MyISAM是默认的存储引擎。提供大量的特性,包括全文索引、压缩、空间函数(GIS)等,但不支持事务和行级锁,一个毫无疑问的缺陷就是崩溃后没法安全恢复。

  MyISAM引擎设计简单,数据以紧密格式存储,因此在某些场景下的性能很好。但最典型的性能问题仍是表锁问题,若是全部的查询都长期处于锁定状态,那么查询的速度无疑是很慢的。

5.三、MySQL内建的其余存储引擎

  Archive引擎,是一个针对高速插入和压缩作了优化的简单引擎。只支持INSERT和SELECT操做,会缓存全部的写并利用zlib对插入的行进行压缩,因此比MyISAM表的磁盘I/O更少。每次SELECT查询都须要执行全表扫描,适合日志和数据采集类应用或者在一些须要更快速的INSERT操做的场合下使用。支持行级锁和专用的缓冲区,因此能够实现高并发的插入。

  CSV引擎,能够将普通的CSV文件(逗号分割值的文件)做为MySQL的表来处理,但不支持索引。将数据存储为CSV文件,而后复制到MySQL数据目录下,就能在MySQL中打开使用。将数据写入到一个CSV引擎表,其余外部程序也能从表的数据文件中读取CSV格式的数据。所以CSV引擎能够做为一种数据交换的机制,很是有用。

  Memory引擎,若是须要快速地访问数据,而且这些数据不会被修改,重启之后丢失也没有关系,那么使用Memory表是很是有用。比MyISAM表快一个数量级,由于数据保存在内存中,不须要进行磁盘I/O。Memory表的结构在重启之后还会保留,但数据会丢失。应用场景为用于查找或者映射表、缓存周期性聚合数据的结果、用于保存数据分析中产生的中间数据。支持Hash索引,所以查找操做很是快。是表级锁,所以并发写入性能较低。不支持BLOB或TEXT类型的列,而且每行的长度固定,即便指定VARCHAR列,实际存储也会转成CHAR,可能致使部份内存的浪费。若是MySQL在执行查询中须要使用临时表保存中间结果,内部使用的临时表就是Memory表。若是中间结果超出Memory表的限制,或者含有BLOB或TEXT字段,则临时表会转换成MyISAM表。

5.四、第三方存储引擎

  OLTP类引擎

    XtraDB存储引擎是基于InnoDB引擎的一个改进版本,已经包含在Percona Server和MariaDB中,它的改进主要集中在性能、可测量性和操做灵活性方面。

  面向列的存储引擎

    MySQL默认是面向行的,每一行的数据是一块儿存储的,服务器的查询也是以行为单位处理的。而在大数据量处理时,面向列的方式可能效率更高。若是不须要整行的数据,能够传输更少的数据,若是每一行都单独存储,那么压缩的效率也会更高。

    Infobright是最有名的面向列的存储引擎,是为数据分析和数据仓库应用设计的。

5.五、选择合适的引擎

5.六、转换表的引擎

  将表的存储引擎转换成另外的一种引擎有不少方法,下面讲述其中的三种方法:

  一、ALTER TABLE

    ALTER TABLE mytable ENGINE = InnoDB;

    优势:能够适用任何存储引擎

    缺点:执行时间长,MySQL会按行将数据从原表复制到一张新的表中,期间可能会消耗系统全部的I/O能力,因此替代方案采用导出与导入,手工进行表的复制

    注意:若是转换表的存储引擎,将会失去和原引擎相关的全部特性。

  二、导出与导入

    使用工具将数据导出到文件,而后修改文件中CREATE TABLE 语句的存储引擎选项,注意同时修改表名。注意在CREATE TABLE 语句前的DROP TABLE语句,不注意可能会致使数据丢失。

  三、建立与查询(CREATE和SELECT)

    综合第一种的高效和第二种的安全,不须要导出整个表的数据,先建立一个新的存储引擎表,而后利用INSERT...SELECT语法来导数据:

    CREATE TABLE innodb_table LIKE myisam_table;

    ALTER TABLE innodb_table ENGINE=InnoDB;

    INSERT INTO innodb_table SELECT * FROM myisam_table;

    若是数据量不大,这样作工做得很好。若是数据量大,能够考虑分批处理,针对每一段数据执行事务提交操做。

    

    假设有主键字段id,重复运行如下语句(最小值x和最大值y进行相应的替换)将数据导入到新表:

    START TRANSACTION;

    INSERT INTO innodb_table SELECT * FROM myisam_table WHERE id BETWEEN x AND y;

    COMMIT;

    新表是原表的一个全量复制,原表还在。若是须要能够删除原表,若是有必要,能够在执行的过程当中对原表加锁,以确保新表和原表的数据一致。

相关文章
相关标签/搜索