在文件系统中,Mysql将每个数据库(也可以称之为schmea)保存为数据目下的一个子目录。数据库和表的定义都使用文件系统的目录和文件来保存,大小写敏感和具体的平台密切相关。在Windows中,大小写是不敏感的,而类Unix中则是敏感的。不同的存储引擎保存数据和索引的方式是不同的,,但表的定义则是在MySQL服务层统一处理。
可以使用如下命令查看表的相关信息;
SHOW TABLE STATUS;
例如
mysql> show table status like 'TABLE_NAME'\G;
*************************** 1. row ***************************
Name: TABLE_NAME
Engine: InnoDB
Version: 10
Row_format: Dynamic
Rows: 91998
Avg_row_length: 656
Data_length: 60407808
Max_data_length: 0
Index_length: 2637824
Data_free: 3145728
Auto_increment: NULL
Create_time: 2019-06-13 18:12:38
Update_time: NULL
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
输出的结果表名这是一个InnoDB表,下面对输出信息简单介绍一下。
Name:表名。
Engine:表存储的引擎类型。在旧版本中,该列的名字叫Type。
Row_format: 行的格式。
Rows:表中的行数,对于MyISAM和其他一些存储引擎,该值是精确的,但对于InnoDB,该值是估算值。
Avg_row_length:平均每行包含的字节数。
Data_length:表数据的大小(以字节为单位)。
Max_data_length:表数据的最大容量,该值和存储引擎有关。
Index_length:索引的小小(以字节为单位)。
Data_free:对于MyISAM表,表示已分配但是目前没有使用的空间。包括了之前删除的行,以及可以被INSERT利用到的空间。
Auto_increment:下一个AUTO_INCREMENT的值。
Create_time:表的创建时间。
Update_time:表数据的最后修改时间。
Check_Time:使用CHECK TABLE 命令或者myisamchk工具最后一次检查表的时间。
Collation:表的默认字符集和字符列排序规则。
Checksum:如果启用,保存的是整个表的实时校验和。
Create_options:创建表时指定的其他选项。
Comment:该列包含了一些其他的额外信息。对于MyISAM表,保存的是表再创建时带的注释,对于InnoDB表,则保存的是InnoDB表空间剩余信息。如果是一个视图,则该列包含“VIEW” 字样的文本。
InnoDB是MySQL的默认事务型存储引擎,也是最重要、使用最广泛的存储引擎,。它被设计用来处理大量的短信(short-lived)事务,短期事务大部分情况是正常提交的,很少回被回滚。InnoDB的性能和自动崩溃恢复特性,使得它在非事务型存储的需求中也备受欢迎。除非特别的原因需要使用其他引擎,否则应该优先考虑InnoDB引擎。InnoDB也是一个非常值得花时间去深入学习的对象。
2008年Oracle 发布了新的InnoDB plugin引擎,其拥有者是InnoDB而不是MySQL(其中原因错综复杂,有兴趣的朋友可以自行了解)。在Oracle收购Sun公司并发布MySQL5.5之前默认还是选择了旧的InnoDB引擎,当然用户可以自行选择使用新的心梗更好,扩展性更加的InnoDB plugin代替旧版本的InnoDB。MySQL5.5以后InnoDB plugin已经是原生编译了,而不是编译成一个插件。
这个现代的InnoDB plugin存储引擎,支持一些新的特性,注入利用排序创建索引(building index bt sorting)、删除或者增加索引时不需要复制全表数据、新的支持压缩的存储格式,新的大型列值,如BLOB的存储方式,以及文件格式管理等。
InnoDB的数据存储在表空间(tablespace)中,表空间是由InnoDB管理的一个黑盒子,由一系列的数据文件组成。InnoDB可以将每个表的数据和索引存放在单独的文件中。InnoDB也可以使用裸设备作为表空间的存储介质,但现代的文件系统使得裸设备不再是必要的选择。
InnoDB采用MVCC来支持高并发,并且实现了四个标准的隔离级别。其默认级别是REOEATABLE READ(可重复读),并且通过间隙锁(next-key locking)策略防止幻读的出现。间隙锁使得InnoDB不仅仅锁定查询涉及的行,还会对索引中的间隙进行锁定,以防止幻影行的插入。
InnoDB 表是基于聚簇索引建立的,InnoDB索引结构和MySQL其他存储引擎有很大的不同,聚簇索引对主键查询有很高的性能。不过它的二级索引(secondary index,非主键索引)中必须包含主键列,所以如果主键列很大的话,其他的所有索引都会很大,因此,若表上的索引较多的话,主键应当尽可能的小。InnoDB的存储格式是平台独立的,也就是说可以将数据和索引文件从Intel平台复制到PowerPC或者Sun SPARC平台。
InnoDB内部做了很多优化,包括从磁盘读取数据时采用的可预测性预读,能够自动在内存中创建hash索引以加速读操作哦的自适应哈希索引(adaptive hash index)以及能够加速插入操作的插入缓冲区(insert buffer)等。
作为事务型的存储引擎,InnoDB通过一些机制和工具支持真正的热备份,oracle提供的Mysql Enterprise Backup 、Percona提供的开源的XtraBackup 都可以做到这一点MySQL的其他存储引擎不支持热备份,要获取一直性视图需要停止对所有表的写入,而在读写混合场景中,停止写入可也意味着停止读取。
InnoDB的行为是非常复杂的,不容易理解。如果使用了InnoDB引擎,笔者强烈建议阅读官方手册中的“InnoDB锁和事物模型”
在MySQL5.1及之前的版本,MyISAM是默认的存储引擎,MyISAM提供了大量的特性、报错全文索引、压缩、空间函数(GIS)等,但不支持事务和行级锁,且最大的缺陷就是崩溃后无法安全恢复。对于只读的数据或者表比较小、可以忍受修复(repair)操作,这样的情况可以使用MyISAM(但默认最好不要使用MyISAM,应当默认使用InnoDB)。
MyISAM会将表存储在两个文件中:数据文件和索引文件,分别以.MYD和.MYI为扩展名。MyISAM可以包含动态或者静态行。MySQL会根据表的定义来决定采用哪种格式。MyISAM表可以存储的行记录数,一般受限于可用的磁盘空间或者操作系统中单个文件的最大尺寸。
加锁与并发
MyISAM对整张表加锁,而不是针对行。读取时会对需要读到的所有表加共享锁,写入时则对表加排他锁。但是在表有读取查询的同时,也可以往表中插入新的记录(这被称为并发插入,CONCURRENT INSERT)。
修复
对于MyISAM表,MySQL可以手工或者自动执行检查和修复操作,但这里说的修复和事务恢复以及崩溃恢复是不同的概念。执行表的修复可能导致一些数据丢失,而且修复操作是非常慢的,可以通过CHECK TABLE TABLE_NAME 检查表的错误,如果有错误可以通过执行REPAIR TABLE TABLE_NAME 进行修复。另外,如果MySQL服务器已经关闭,也可以通过命令行工具 myisamchk 进行检查和修复操操作。
索引特性
对于MyISAM表,即使是BLOB和TEXT等长字段,也可以基于前500 个字符创建索引,MyISAM也支持全文索引,这是一种基于分词创建的索引,也可以支持复杂的查询。
延迟更新索引键(Delayed Key Write)
创建MyISAM表的时候,如果指定了DWELAY_KEY_WRITE选项,在每次修改执行完成时,不会立刻将修改的索引数据写入磁盘,而是会写到内存中的键缓冲区(in-memory key buffer),只有在清理键缓冲区或者关闭表的时候才会将对应的索引快写入磁盘,这种方式可以极大的提升写入性能,但是在数据库或者主机崩溃时会造成索引的损坏,需要执行修复操作,延迟更新索引建的特性,可以在全局设置,也可以在单个表设置。
如果表再创建并导入数据以后,不会再进行修改操作,那么这样的表或许适合采用MyISAM压缩表。
可以使用 myisampack 对 MyISAM表进行压缩(也叫打包pack)。压缩表修改数据的话,只能先解压,修改数据,再次压缩。压缩表可以极大的减少磁盘空间占用,因此也可以减少磁盘I/O,从而提升查询性能。压缩表也支持索引,但索引也是只读的。
以现在的硬件能力,对大多数应用场景,读取压缩表数据时的解压带来的开销影响并不大,而减少I/O带来的好处则要大得多。压缩时表中的记录是独立压缩的,所以读取单行的时候不需要去解压整个表(甚至也不解压行所在的整个页面)。
MyISAM引擎设计简单,数据已紧密的格式方式存储,所以在某写场景下的性能很好。MyISAM有一些服务器级别的性能扩展限制,比如对索引建缓冲区(key cache)的Mutex锁,MariaDB基于段(segment)的索引建缓冲区机制来避免该问题。但MyISAM最典型的性能问题还是表锁的问题,如果你发现所有的查询都长期处于"locked" 状态,那么毫无疑问表锁就是罪魁祸首。
MySQL还有一些特殊用途的存储引擎,在不断更新的过程中,有些可能不再支持,继续支持的,需要明确地启用后才能使用。
Archive引擎
Archive存储引擎只支持INSERT 和 SELECT操作,在MySQL5.1之前不支持索引。Archive引擎会缓存所有的写并利用zlib对插入的行进行压缩,所以比MyISAM表的磁盘I/O更少,但是每次SELECT 查询都需要执行全表扫描。所以Archive表适合日志和数据采集类应用,这类的应用做数据分析时往往需要全表扫描。或者在一些需要更快速的INSERT操作的场合下也可以使用。
Archive 引起支持行级锁和专用的缓冲区,所以可以实现高并发的插入。在一个查询开始知道返回表中存在的所有行数之前,Archive引擎会组织其他的SELECT执行,以实现一致性读。另外,也实现了批量插入在完成之前对读操作时不可见的。这种机制模仿了事务和MVCC的一些特性,但Archive引擎不是一个事务性的引擎,而是一个针对高速插入和压缩做了优化的简单引擎。
Blackhole引擎
Blackhole引擎没有实现任何的存储机制,它会丢弃所有插入的数据,不做任何保存。但是服务器会记录Blackhole表的日志,所有可以用于复制数据到备库,或者只是简单地记录到日志。这种特殊的存储引擎可以再在一些特殊的复制架构和日志审核时发挥作用。这种方式可控性较差,因此不推荐。
CSV引擎
CSV引擎可以将普通的CSV文件(逗号分隔值的文件)作为MySQL的表来处理,但这种表不支持索引。CSV引擎可以在数据库运行时拷入或者拷出文件。可以将Excel 等电子表格软件中的数据存储为CSV文件,然后复制到MySQL数据目录下,就在MySQL中打开使用。同样,如果将数据写入到一个CSV引擎表,其他的外部程序也能立即从表的数据文件中读取CSV格式的数据。因此CSV引擎可以作为一种数据交换的机制,非常有用。
Federated 引擎
Federated引擎是访问其他MySQL服务器的一个代理,它会创建一个到远程MySQL服务器的客户端连接,并将查询传输到远程服务器执行,然后提取或者发送需要的数据。最初设计该存储引擎是为了企业级数据库如Microsoft SQL Server和Oracle的类似特性竞争的,可以说更多的是一种时长行为,尽管该引擎看起来提供了一种很好的跨服务器的灵活性,但也经常带来问题,因此默认是禁用的。MariaDB使用了它的一个后续改进本叫做FederatedX。
Memory引擎
顾名思义。如果需要快递地访问数据,并且这些数据不会被修改,重启以后会丢失也没有关系,那么使用Memory表是非常有用的。Memory表至少比MyISAM表要快一个数量级,因为所有的数据都保存在内存中,不需要进行任何的磁盘I/O,Memory表的结构在重启以后还会保留,但数据会丢失。
Memory表再很多场景可以发挥好的作用
Memory表支持Hash索引,因此查找操作非常快。尽管如此Memory表还是无法取代传统的基于磁盘的表。Memory表是表级锁,因此并发写入的性能较低。它不支持BLOB或TEXT类型的列,并且每行的长度是固定,所以即使指定了VARCHAR列,实际存储时也会转换成CHAR,这可能导致部分内存的浪费
如果MySQL在执行查询的过程中需要使用临时表来保存中间结果,内部使用的临时表就是Memory表。。如果中间结果太大超出了Memory表的限制,或者含有BLOB或TEXT字段,则临时表会转换成MyISAM表。在后续的章节还会继续讨论该问题。
PS:Memory表和临时表是有区别的,临时表是指使用CREATE TEMPORARY TABLE 语句创建的表,他可以使用任何存储引擎,临时表只在单个连接中可见,当连接断开时,临时表也将不复存在。
Merge 引擎
Merge引擎是MyISAM引擎的一个变种。Merge表是由多个MyISAM表合并而来的虚拟表,如果将MySQL用于日志或者数据仓库类型应用,该引擎可以发挥作用。但是引入分区功能后,该引擎已经被放弃。
NDB集群引擎
2003年,当时的MySQL AB公司从索尼爱立信公司收购了NDB数据库,然后开发了NDB集群存储引擎,作为SQL和NDB原生协议之间的接口。MySQL服务器,NDB集群存储引擎,以及分布式的,share-noting的、容灾的、高可用的NDB数据的组合、被称为MySQL集群。