MySQL存储引擎差别化实验

本篇把MySQL最经常使用的存储引擎给你们作一个介绍,而后经过插入、修改和并发实验来了解和验证一下它们之间的一些差别。php

 

1、MySQL存储引擎简介mysql

存储引擎在MySQL结构里占据核心的位置,是上层抽象接口和存储的物理文件之间的桥梁。每一种storage engine 架构组件都是根据特定的场合来设计的,负责数据的 I/O 操做,并启用一些特性的支持。linux

MySQL存储引擎被设计为插件式结构,每种存储引擎可从运行的mysql里动态加载或卸载。咱们能够在客户端链接后用show plugins;查看当前加载的插件,用install plugin xxx;或者 uninstall plugin xxx;来安装或卸载。sql

 

查看服务器当前支持的引擎命令:数据库

mysql> show engines;apache

 

主要的几种引擎介绍以下:缓存

InnoDB:支持事务操做,支持行级锁,支持外键。独立表结构的花每一个表单文件存储,是MySQL5.5以后的默认引擎。服务器

MyISAM:使用普遍,数据量不是特别大时性能很高,是5.5以前的默认引擎。session

Memory:数据直接放在内存,极快的访问速度,可是空间很受限。架构

MRG_MYISAM:能够把MyISAM表分组管理。

Federated:能够把不一样物理服务器链接成一个逻辑服务器,适合分布式管理。

CSV:导入导出成CSV格式,便于和其余软件数据交换。

 

咱们能够配置php.ini文件或者在server启动时,能够经过--default-storage-engine参数来指定默认的存储引擎。也能够在mysql运行状态下动态改变默认引擎:

show variables like 'default_storage_engine';

SET default_storage_engine=MYISAM;

 

数据库的每一个表可使用不一样的引擎:

create table t_a(uid int,uname varchar(50)) engine=innodb;

也能够动态修改表的引擎:

alter table t_a engine=MyISAM;

 

2、MySQL存储引擎的文件组成与备份

MySQL主要的动态文件有日志文件、配置文件和存储引擎的数据文件

一、日志文件

种类很是多,咱们也能够在这些变量里找到innodb的特殊日志文件:

show variables like '%log%';

二、配置和链接文件

my.cnf是数据库的主要配置文件,若是咱们作了主从配置,则还有master.info等配置信息文件。

linux下支持tcp和socket链接,能够经过配置my.cnf或者链接时增长参数来肯定mysql --protocol=tcp,若是是socket方式则通常会经过socket文件来链接/tmp/mysql.sock。

三、数据文件

每一种存储引擎都有.frm 表元数据文件。而后每种引擎都有本身的一些特有特有格式的文件:

.myd (MyData)是MyISAM数据文件,.myi (MyIndex)是MyISAM索引文件(b-tree、full-text等)。

innodb的共享表空间存在ibdata文件里,若是配置成独享表空间的话(mysql默认)每一个表还会有对应.ibb文件。咱们能够经过变量查询和设置这些配置:

show variables like ‘%innodb%’;  其中innodb_file_per_table设置是不是独享表空间,innodb_data_file_path 和innodb_data_home_dir用来指定表的存放位置。

 

备份:

一、逻辑备份

逻辑备份是不停机的状况下比较好的备份方式,经过mysqldump或者其余方式来导出sql语句。

二、物理备份

物理备份在某些状况是更加直接和快速的方式。myisam引擎由于是非事务没有独立日志,通常备份3个文件便可,也能够经过mysqlhotcopy来进行物理备份。

innodb 由于事物须要有日志文件,若是在运行状态则不能手工来备份,须要一些商业化的工具好比ibbackup来支持物理备份。

三、主从物理备份

由于物理备份通常须要锁库,在线上数据库上咱们若是设置了主从服务器而且有多台从库的话,能够暂停一台从库,而后实行物理备份。

 

3、插入和更新数据

咱们先建立3个引擎的数据表user_myisam、user_innodb、user_memory,表的结构是同样的:

create table user_myisam (

       uid int auto_increment,

       uname varchar(50) not null default '',

       type tinyint not null default 0,

       ctime timestamp not null default current_timestamp,

       primary key (uid)

) engine=myisam, charset=utf8;

 

  

咱们在生成数据时,可使用一条条数据插入、导入sql文件、或者批量插入的方式进行。

导入sql文件是有大小限制的,咱们能够经过max_allowed_packet变量来查看,通常默认为1M,因此导入大量数据时须要增大这个变量:

show variables like 'max_allowed_packet';

显然,数据量很大时,批量插入的方式是效率最高的:

insert into tbl values(),(),()...

通过对比,虽然memory引擎插入和查询修改的速度都极快,单只支持几万行数据,即便调大了内存参数也只能支持10多万行。因此memory通常用在一些数据量比较小的特殊场合,好比在线用户表、或者缓存一些配置信息等。

咱们用批量插入的方式把myisam和innodb的表各插入了1千万行数据(每次插入1万行或更多),myisam的速度要稍快些,没有调优的状况下几分钟时间就能够了。

 

更新和查询的数据对比:

在一个进程操做的状况下,myisam的更新和查询速度都会稍快于innodb。

特别注意的一点是,innodb查询表的行数须要全表扫描,速度会很是慢,查询1千万行数据的表最多时要六、7s,因此在项目里必定要控制innodb表的总数查询,必定要缓存。而myisam由于保存了总行数是极快的。

 

4、innodb的事务支持和锁

innodb的事物支持4种隔离级别:

read uncommitted:脏读,在本身的事务里能看到别的事务修改但未提交的数据。

read committed:不可重复读,虽然别的事务未提交的数据看不到,可是提交后就能够了,因此不能屡次读取,数据可能不一致。

repeatable read:可重复读,事务作了隔离,但仍是能够并发的。

serializable:串行,最严格的方式,事务单行处理,不会并行。

查看当前和全局的事务隔离级别:

SELECT @@GLOBAL.tx_isolation, @@tx_isolation;

能够经过如下命令来改变设置:

set global transaction isolation level read uncommitted;

咱们能够经过2个session而后设置set autocommit=0来进行测试和验证这4种事务隔离级别的差异,在本身的项目里也能够根据状况来改变。越高的隔离级别对性能影响越大,innodb默认是repeatable read方式。

 

mysql有3种锁:

一、表级锁:myisam的默认形式,开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的几率最高,并发度最低。能够查看表锁的一些状况:

show status like 'table%';
二、行级锁:innodb的默认形式,开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的几率最低,并发度也最高。

须要注意的是,innodb只有在能利用索引的操做时才执行行级锁,若是查询或更新操做不能利用索引仍是会使用表级锁的。查看行锁状态:

show status like 'innodb_row_lock%';
三、页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度通常。

 

5、并发测试与参数调优总结

虽然在上面单进程的状况下,myisam在插入查询和更新等操做中性能都比较高,可是在咱们模拟高并发的状况下,能够看出innodb的销量明显占优了。

咱们用apache的ab工具来测试3000次30个并发的请求,每一个请求在1千万数据里随机找5行数据进行修改和查询(用到索引),测试结果以下:

myisam的测试数据:

innodb的测试结果:

myisam的一些参数优化:

read_buffer_size缓存大小

设置concurrent_insert为2,在尾部插入数据,不影响select

打开delay_key_write

 

innodb的一些参数:

设置事务提交后数据保存方式:

innodb_flush_log_at_trx_commit

0 每秒保存 1 每事务保存 2 系统决定

 

innodb_buffer_pool缓存大小:

show status like 'innodb_buffer_pool%';

 

能够用show engine innodb status\G查看innodb的一些状况:

innodb_read_io_threads读写进程数

innodb_write_io_threads

innodb_io_capacity合并写入数量

innodb_io_capacity=5000;

set global innodb_stats_on_metadata=0;关闭元数据更新

 

 

通过咱们的一些操做对比,能够看出:

Memory虽然是高效的引擎,可是因为是临时数据并且有数据量的限制,适合与性能要求高数据量小的地方,和缓存的效果相似。

MyISAM适合数据量不是特别大并发不过高的大部分场合,性能都占优,而且也支持全文检索。若是不须要事务支持的话MyISAM绝对是最优的方式。

而InnoDB 则更适合与大并发大数据量的场合,除了支持事务,在高并发时行级锁的优点就会发挥出来。固然咱们须要在代码和设计里去规避innodb自己的一些的问题,例如尽量使用到索引,缓存表的行数等。

相关文章
相关标签/搜索