MySQL 中 InnoDB 与 MyISAM 区别及选择
MySQL 中,写锁优先于读锁;因为 MySQL 认为写请求一般比读请求更重要
MySQL 存储引擎
-
MyIsAM
- 表级锁
-
InnoDB
- 支持行级锁,默认采用行级锁
- 支持表级锁
-
MEMORY
- 表级锁
-
BDB
- 支持页面锁,默认采用页面锁
- 支持表级锁
MySQL 锁机制
-
表级锁
- 开销小,加锁快
-
不会出现死锁
- 原因:一次性获得 SQL 语句所需要的全部锁
- 锁定粒度大,发生锁冲突的概率高,并发度最低
-
行级锁
- 开销大,加锁慢
- 会出现死锁
- 锁定粒度最小,发生锁冲突的概率最低,并发度最高
-
页面锁
- 开销和加锁速度界于表锁和行所之间
- 会出现死锁
- 锁定粒度界于表锁和行锁之间,并发度一般
1、InnoDB
四大特性:插入缓冲(insert buffer),二次写(double write),自适应哈希索引(ahi),预读(read ahead)
- 支持事务处理等
- 不加锁读取
- 支持外键
- 支持表、行(默认)锁
- 现支持 Full-text 类型的索引
- 不保存表的具体行数,扫描表来计算有多少行
- Delete 表时,是一行一行的删除
- InnoDB 中必须包含 AUTO_INCREMENT类型字段的索引
- InnoDB 表被存放在两个文件,frm 文件存放每个表的元数据,包括表结构和定义等,idb 文件存放表的数据和索引文件
- 表格很难被压缩
-
InnoDB B+Tree 的体现是以主键为索引来组织数据的存储,当我们没有显示的建立主键索引的时候,InnoDB 引擎会隐式的生成一个 6 位的 int 型的索引来作为它的主键索引以组织数据的存储
2、MyISAM
- 不支持事务,回滚将造成不完全回滚,不具有原子性
- 不支持外键
- 支持表锁
- 支持全文搜索
- 保存表的具体行数,不带 where 条件时,直接返回保存的行数
- Delete 表时,现 Drop 表,再重建表
- MyISAM 表被存放在三个文件,frm 文件存放表格定义,MYD(MYData)存放数据文件,MYI(MYIndex)存放索引文件
- 跨平台很难直接 copy
- MyISAM 中可以使用 AUTO_INCREMENT 类型字段建立联合索引
- 表格可以被压缩
- 执行查询语句( select )前,会自动给涉及的所有表加读锁(表共享读锁)
- 执行更新操作( update, delete, insert )前,会自动给涉及到的所有表加写锁(表共享写锁)
- 读锁和写锁是互斥的,读写操作是串行的
-
如果MyISAM 表的中间没有被删除行的话,那么 MyISAM 是允许在一个进程读表的同时,另一个进程从表位做插入记录的;但是 InnoDB 不支持
Q : 一个进程请求 MyISAM 表的读锁,同时另一个进程也请求同一个表的写锁;MySQL 怎么处理?
A : 写进程先获得锁,即使读请求先到锁等待队列,写请求后到,写锁也会插到读锁请求之前!因为 MySQL 认为写请求一般比读请求重要。
这也正是 MyISAM 表不太适合有大量更新操作和查询操作的应用的原因,因为大量的更新操作会造成查询操作很难获得到读锁,从而可能永远阻塞
可以通过一些设置调节 MyISAM 的调度行为
- 通过指定启动参数low-priority-updates,使得 MyISAM 引擎默认给予读请求优先的权力
- 通过执行命令 SET LOW_PRIORITY_UPDATES=1,使得该连接发出的更新请求优先级降低
- 通过指定INSERT, UPDATE, DELETE 语句的LOW_PRIORITY 属性,降低该语句的优先级
-
也可给系统参数 max_write_lock_count 设置一个适当的值,当一个表的读锁达到这个值后,MySQL 就暂时将写请求的优先级降低,给读请求获得锁的机会
3、选择(参考实际选用)
-
MyISAM:
- 不需要事务支持的场景
- 如果系统读多,写少,对原子性要求低,那么 MyISAM 时最好的选择。因为 MyISAM 相对简单,所以在效率上要优于 InnoDB。
- MyISAM 恢复速度快,可直接用备份覆盖恢复。
-
InnoDB:
- 要支持事务的场景
- 如果系统读少,写多的时候,尤其是并发写入高的时候。
|
|
|