本篇把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由于保存了总行数是极快的。
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自己的一些的问题,例如尽量使用到索引,缓存表的行数等。