MySQL引擎与锁机制
一、引言
在日常开发中,MySQL数据库应该都没少使用吧。对MySQL数据库的引擎应该也有所了解,下面就详细的学习一下MySQL数据库的Innodb和MyIASM两种引擎及各自的优缺点、锁机制,也来巩固一下自己对这块知识的掌握。
1、查看MySQL支持的存储引擎
说明:
Support列, YES表示当前版本支持这个存储引擎, DEFAULT表示该引擎是默认的引擎。NO表示不支持该存储引擎。可以看出,InnoDB是默认的存储引擎。在5.1版之前,MyISAM是MySQL的默认数据库引擎。
2、查看当前数据库的存储引擎
3、查看表的存储引擎
二、存储引擎
上面介绍了如何查看数据库和表的引擎命令,下面来看看如何修改默认的存储引擎。
1、存储引擎的基本设置
(1)如何修改MySQL的默认存储引擎?
修改my.ini或my.cnf配置文件,在配置文件里面[mysqld]节点下增加或修改参数 default-storage-engine,然后重启数据库服务。
然后检查默认存储引擎,就会看到MyISAM为默认存储引擎
(2)如何修改表的存储引擎?
(3)创建表的时候如何指定存储引擎?
2、两种常用的存储引擎
在MySQL数据库中,常用的引擎主要是:Innodb和MyIASM。
(1)Innodb引擎
Innodb引擎提供了对数据库ACID事务的支持,并且还提供了行级锁和外键的约束,它的设计目标就是处理大数据容量的数据库系统。MySQL运行的时候,Innodb会在内存中建立缓冲池,用于缓冲数据和索引。但是,该引擎是不支持全文搜索的。同时,启动也比较的慢,它是不会保存表的行数的。当进行select count(*) from table指令的时候,需要进行扫描全表。所以当需要使用数据库的事务时,该引擎就是首选。由于锁的粒度小(行锁),写操作是不会锁定全表的,只锁定某一行,所以在并发度较高的场景下使用会提升效率的。
(2)MyIASM引擎
MyIASM在5.1版本之前是MySQL默认引擎,但它不提供事务的支持,也不支持行级锁和外键。因此当执行insert插入和update更新语句时,即执行写操作的时候需要锁定整张表,所以会导致效率会降低。不过和Innodb不同的是,MyIASM引擎是保存了表的行数,当进行select count(*) from table语句时,可以直接的读取已经保存的值而不需要进行扫描全表。所以,如果表的读操作远远多于写操作时,并且不需要事务的支持的。可以将MyIASM作为数据库引擎的首选。
(3)两种引擎在索引上使用的数据结构
InnoDB和MyISAM两种引擎所使用的索引的数据结构都是B+树。
而Innodb引擎的索引的数据结构也是B+树,只不过数据结构中存储的都是实际的数据,这种索引有被称为聚集索引。索引在下篇文章详述。
3、两种引擎的详细比较
(1)事务支持
(2)存储结构
(3)存储空间
(4)可移植性、备份及恢复
(5)事务支持
(6)AUTO_INCREMENT
(7)表锁差异(☆☆☆☆)
注意:MyISAM锁的粒度是表级,而InnoDB支持行级锁定。简单来说就是, InnoDB支持数据行锁定,而MyISAM不支持行锁定,只支持锁定整个表。即MyISAM同一个表上的读锁和写锁是互斥的,MyISAM并发读写时如果等待队列中既有读请求又有写请求,默认写请求的优先级高,即使读请求先到,所以MyISAM不适合于有大量查询和修改并存的情况,那样查询进程会长时间阻塞。因为MyISAM是锁表,所以某项读操作比较耗时会使其他写进程饿死。
(8)全文索引
(9) 表主键
(10)表的具体行数
(11) CURD操作
(12)外键
4、两种引擎的选择:
通过上述的分析,基本上可以考虑使用InnoDB来替代MyISAM引擎了,原因是InnoDB自身很多良好的特点,比如事务支持、存储过程、视图、行级锁定等等。在并发很多的情况下,相信InnoDB的表现肯定要比MyISAM强很多。
(1)当大容量的数据集时,趋向于选择Innodb。因为它支持事务处理和故障的恢复。Innodb可以利用数据日志来进行数据的恢复。主键的查询在Innodb也是比较快的。
(2)大批量的插入语句时(这里是INSERT语句),在MyIASM引擎中执行的比较的快,但是UPDATE语句在Innodb下执行的会比较的快,尤其是在并发量大的时候。
(3)MyISAM管理非事务表。它提供高速存储和检索,以及全文搜索能力。如果应用中需要执行大量的SELECT查询,那么MyISAM是更好的选择。
但是实际场景中,具体情况要具体分析,一般而言可以遵循以下几个问题:
数据库是否有外键?
是否需要事务支持?
是否需要全文索引?
数据库经常使用什么样的查询模式?在写多读少的应用中还是Innodb插入性能更稳定,在并发情况下也能基本,如果是对读取速度要求比较快的应用还是选MyISAM。
数据库的数据有多大?大尺寸倾向于innodb,因为事务日志,故障恢复。
5、MyISAM和InnoDB对比总结
三、MySQL锁机制
锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(如CPU、RAM、I/O等)的争用外,数据也是一种供许多用于共享的资源,如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而已显得尤其重要,也更加复杂。
1、锁的分类:
(1)从对数据操作的类型分为:
(2)从对数据操作的粒度分为:
2、锁的操作:
查看表上加过的锁:
手动增加表锁:
释放表锁:
3、间隙锁:
当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有记录的索引项加锁,对于键值在条件范围内但并不存在的记录,叫做“间隙”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁(Next-Key锁)。此时在间隙中进行插入操作会被阻塞。
间隙锁的危害:
(1)因为Query执行过程中通过范围查找的话,它会锁定整个范围内所有的索引键值,即使这个键值并不存在;
(2)间隙锁有一个比较致命的弱点,就是当锁定一个范围键值之后,即使某些不存在的键值也会被无辜的锁定,而造成在锁定的时候无法插入锁定键值范围内的任何数据,在某些场景下这可能会对性能造成很大的危害;
4、MyISAM引擎的锁机制
该引擎在执行查询语句(select)前,会自动给涉及的所有表加读锁,在执行增删改操作前,会自动给涉及的表加写锁;
MySQL的表级锁有两种模式:
结论:
(1)对MyISAM表的读操作(加读锁),不会阻塞其他进程对同一表的读请求,但会阻塞对同一表的请求,只有当读锁释放后,才会执行其他进程的写操作;
(2)对MyISAM表的写操作(加写锁),会阻塞其他进程对同一表的读和写操作,只有当写锁释放后,才会执行其他进程的读写操作;
简而言之:就是读锁会阻塞写,但是不会阻塞读。而写锁则会把读和写都读锁。
5、索引失效,行锁会变表锁(☆☆☆☆)
(1)尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁;
(2)合理设计索引,尽量缩小锁的范围;
(3)尽可能较少检索条件,避免间隙锁;
(4)尽量控制事务大小,减少锁定资源量和时间长度;
(5)尽可能低级别事务隔离;
四、小结:
(1)InnoDB与MyISAM的最大不同有两点:一是支持事务(Transaction),二是采用了行级锁;
(2)InnoDB存储引擎由于实现了行级锁定,虽然在锁定机制的实现方面所带来的性能损耗可能比表级锁会更高一些,但是在整体并发处理能力方面要远远优于MyISAM的表级锁定的,当系统并发量较高的时候,InnoDB的整体性能和MyISAM相比就会有比较明显优势了;
(3)但是,InnoDB的行级锁同样也有其脆弱的一面,当我们使用不当的时候,可能会让InnoDB的整体性能表现不仅不能比MyISAM高,甚至可能更差;