提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
MySQL5.5之前版本默认存储引擎
MySQL大部分系统表、临时表使用的存储引擎
临时表:在排序、分组等操作中,当数量超过一定大小后,由查询优化器建立的临时表
MyISAM存储引擎表由MYD(数据文件)和MYI(索引文件)组成。
MyISAM使用的是表级锁,在对表中数据进行修改时,会对整个表进行加锁。在对表中数据进行读取时,也需要对表加共享锁。读取和写入操作是互斥的。在一些情况下,当我们对表中数据进行读取时,也可以在表的末尾加上数据。
MyISAM对于读写混合的并发性不是很好,如果只是读的操作的话,并发性是可以接受的。因为共享锁不会阻塞共享锁。
MyISAM支持对由于意外关闭而损坏的MyISAM表进行修复操作。(这里指的修复不是事务恢复,因为MyISAM就不是事务型的存储引擎,也没有进行事务恢复所需要的相关日志。)
要注意对MyISAM表进行数据修复可能会导致数据丢失。
除了repair能对MyISAM表进行修复,MySQL还提供了一个命令行工具myisamchk,也可以对MyISAM表进行修复。要注意使用这个工具对MyISAM表修复的话,需要停止MySQL服务,否则容易造成更大的损坏。
MyISAM支持全文索引,在MySQL5.7之前版本中唯一原生支持全文索引的官方存储引擎。
对于一个导入数据后不会再做修改操作的表,我们可以对这样的表做压缩操作,可以减少磁盘IO。
可以使用myisampack命令来压缩表中的数据,由于表中数据是独立进行压缩的,所以读取单行数据的时候不必对整个表进行解压。
如果需要存储大表,则需要修改MAX_Rows(最大行数)和AVG_ROW_LENGTH(平均行长度)
对于大表来说,这两个参数的修改会导致整个表的重建,会需要一些时间。
版本 > MySQL5.0时单表默认最大为256TB
MySQL5.5及之后的默认存储引擎
InnoDB是事务型引擎,支持事务的ACID特性的
InnoDB使用表空间进行数据存储
innodb_file_per_table
ON:独立表空间,为每个InnoDB表创建文件--tablename.ibd
OFF:系统表空间,把数据存储到共享表空间--ibdataX(“X”是数字)
在MySQL5.6之前的innodb_file_per_table是OFF
在一个繁忙的系统中,系统表空间在不断增长,一旦磁盘空间出现不足,就需要在系统中删除不需要的数据。
但是在删除了之后,会发现系统表空间并不会缩小,这个时候会出现大量的磁盘碎片。要收割系统表空间的唯一方法就是把数据库中所有InnoDB表导出,删除InnoDB相关的系统表空间文件后,重启数据库服务器来进行表空间的重建,再导入数据。
使用系统表空间进行数据存储,面临的问题就是无法很容易收缩系统文件,造成大量的空间浪费,磁盘碎片,从而降低系统的性能。
独立表空间可以通过optimize table命令收缩系统文件。
这样就比对整个系统进行表空间重建要快得多,而且不用重启数据库服务器
结论:使用系统表空间比使用独立表空间要好得多。
对于系统表空间来说,由于只有一个文件,对多个表进行数据刷新时,从文件系统层面来说是顺序进行的,所以会产生一定的IO瓶颈。
对于独立表空间来说,每个表都有自己的表空间文件,在数据写入时,可以利用多个文件增加IO处理的性能。
结论:对于频繁写入操作的系统来说,不太适合使用系统表空间来统一存储数据,而是要使用独立表空间。
步骤:
把系统表空间迁移到独立表空间后,选择系统表空间里还有什么内容呢?
使用了两个特殊的日志:
Redo Log 存储的是已提交的事务,Undo Log 存储的是未提交的事务。
Redo Log 由两部分组成:
内存中的重做日志缓冲区 + 文件系统中的重做日志文件
show variables like 'innodb_log_buffer_size';
innodb_log_buffer_size 设置重做日志缓冲区的大小,单位为字节。
因为每隔一秒钟就会把缓冲区刷新到硬盘上,所以不需要设置太大。
show variables like 'innodb_log_files_in_group';
innodb_log_files_in_group 这个参数决定了会产生几个logfile文件
innodb_log_files_in_group决定产生几个ib_logfileX文件
帮助未提交事务进行回滚和实现MVCC,
当对InnoDB表中的数据进行修改时,不仅产生 Redo Log 还会产生 Undo Log,这样如果用户的事务或者语句失败因为某种原因失败,或者使用ubat语句回滚时,就需要使用到 Undo Log 中的信息了。
Redo Log 基本是顺序写入的,在数据库运行时,不需要对 Redo Log 进行读取操作。
而 Undo Log 是需要进行随机的读写的,MySQL5.6版本以后,可以独立于系统表空间而存在,可以把 Undo Log 存储在固态存储设备上,以获得更好的性能。
行级锁的特点是,在进行写操作时我们所用的资源更少,这样能支持的并发就会更多。
InnoDB支持的行级锁是由存储引擎实现的,MySQL服务层完全不了解存储引擎中锁的实现方式。
show engine innodb status
适合大多数OLTP应用
5.7之后InnoDB就可以支持全文索引与空间函数了
锁是数据库系统区别于文件系统的重要特性
锁的主要作用是管理共享资源的并发访问
锁用于实现事务的隔离性
\ | 写锁 | 读锁 |
---|---|---|
写锁 | 不兼容 | 不兼容 |
读锁 | 不兼容 | 兼容 |
对于InnoDB来说,读锁和写锁都是行锁。
InnoDB的锁的实现要比这个更复杂。
一个例子:
连接一:开启一个事务更新某一行,不提交。
连接二:查询该行。
发现连接二的查询并没有被连接一阻塞。
这就是InnoDB的独到之处,在第二个连接中查询到的结果其实是存储在 undo log 中的版本。
锁的粒度就是指被加锁单元的最小单位。(行、页、表…)
最理想的粒度就是只对需要修改的数据进行精确的锁定,相互之间不产生阻塞,并发性自然也就会更高
MySQL中最基本,开销最小的策略,开销小那么同时并发性也就低
InnoDB中的表级锁通常是由MySQL服务层实现的。虽然InnoDB实现的是行级锁,但是一些情况下MySQL服务层还是会加表级锁。
比如 lock table操作时
例子:
连接一:
lock table tablename write;
连接二:
select * from tablename
发现连接二被阻塞
连接一:
unlock tables;
然后第二个连接的操作被执行
行级锁可以最大程度上支持并发处理,同时锁的开销也比表级锁大。
行级锁只在存储引擎层实现,MySQL服务层并没有对行级锁做任何实现。
什么是阻塞?
因为不同锁之间的兼容性的关系,有些时刻一个事务中的锁需要等待另一个事务中的锁释放占用的资源,而形成阻塞。
阻塞是为了确保事务的可以并发且可以正常运行,当一个系统中出现大量阻塞,往往也意味着系统中存在着问题。
过多的阻塞可以使数据库连接大量堆积,占用大量系统资源,使系统性能整体下降。
什么是死锁?
两个或两个以上的事务,在执行过程中相互占用对方等待的资源,产生的一种异常。
数据库系统会自动发现死锁,并且在多个死锁的事务中选出资源占用最少的事务来进行回滚操作,这样来使其他事务正常运行。
死锁是可以由系统自动处理的。有少量的死锁并不会对系统造成什么影响,但是如果一个系统中频繁出现大量死锁则还是需要留意了。