支持事务。
支持行级锁和表级锁,能支持更多的并发量。
查询不加锁,彻底不影响查询。
支持崩溃后恢复。
不支持事务。
使用表级锁,若是数据量大,一个插入操做锁定表后,其余请求都将阻塞。
索引,都是实如今存储引擎层的。html
一、普通索引:最基本的索引,没有任何约束。
二、惟一索引:具备惟一性约束。
三、主键索引:特殊的惟一索引,不容许有空值。
四、复合索引:将多个列组合在一块儿建立索引,能够覆盖多个列。
五、外键索引:只有InnoDB类型的表才可使用外键索引,保证数据的一致性、完整性和实现级联操做。
六、全文索引:MySQL 自带的全文索引只能用于 InnoDB、MyISAM ,而且只能对英文进行全文检索,通常使用全文索引引擎。(经常使用的全文索引引擎的解决方案有 Elasticsearch)
- 0、 应尽可能避免在 where 子句中对字段进行 null 值判断,不然将致使引擎放弃使用索引而进行全表扫描 。
- 一、 应尽可能避免在 WHERE 子句中使用 != 或 <>操做符, 不然引擎将放弃使用索引而进行全表扫描。 优化器将没法经过索引来肯定将要命中的行数,所以须要搜索该表的全部行。 注意,column IS NULL 也是不可使用索引的。
- 二、 应尽可能避免在 where 子句中使用 or 来链接条件,若是一个字段有索引,一个字段没有索引,将致使引擎放弃使用索引而进行全表扫描。
- 三、 应尽可能避免在 WHERE 子句中对字段进行表达式操做,这将致使引擎放弃使用索引而进行全表扫描。
- 四、 应尽可能避免在 WHERE 子句中对字段进行函数操做,这将致使引擎放弃使用索引而进行全表扫描。
- 五、 不要在 WHERE 子句中的 = 左边进行函数、算术运算或其余表达式运算,不然系统将可能没法正确使用索引。
- 六、 尽可能使用数字型字段,若只含数值信息的字段尽可能不要设计为字符型,这会下降查询和链接的性能,并会增长存储开销。这是由于引擎在处理查询和链接时会逐个比较字符串中每个字符,而对于数字型而言只须要比较一次就够了。
- 七、 列类型是字符串类型,查询时必定要给值加引号,不然索引失效。
- 八、 LIKE 查询,% 不能在前,由于没法使用索引。若是须要模糊匹配,可使用全文索引。
- 九、 尽可能的扩展索引,不要新建索引。
- 十、 复合索引遵循前缀原则。索引的最左匹配特性
为了描述B-Tree,首先定义一条记录为一个二元组 [key, data] ,key 为记录的键值,对应表中的主键值,data 为一行记录中除主键外的数据。
mysql
InnoDB存储引擎就是用 B+Tree 实现其索引结构。面试
B+树结构中有: sql
面试题1:为何不用B树做为索引?
从 B-Tree 结构图中能够看到,每一个节点中不只包含数据的 key 值,还有 data 值。而每个页的存储空间是有限的,若是 data 数据较大时将会致使每一个节点(即一个页)能存储的 key 的数量很小,当存储的数据量很大时一样会致使 B-Tree 的深度较大,增大查询时的磁盘 I/O 次数,进而影响查询效率。在 B+Tree 中,全部数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储 key 值信息,这样能够大大加大每一个节点存储的 key 值数量,下降 B+Tree 的高度。
在 B+Tree 中,根据叶子节点的内容,索引类型分为主键索引和非主键索引。
数据库
innodb中的主键索引和实际数据绑定在一块儿,也就是说Innodb的一个表必定要有主键索引。若是一个表没有手动创建主键索引,Innodb会查看有没有惟一索引,若是有,则选用惟一索引做为主键索引;若是连惟一索引也没有,则会默认创建一个隐蔽的主键索引,这个隐形字段长度为6个字节,类型为长整形(用户不可见)。并发
1)主键索引:
函数
在InnoDB中,表数据文件自己就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,所以InnoDB表数据文件自己就是主索引。
高并发
(图inndb主键索引)是InnoDB主索引(同时也是数据文件)的示意图,能够看到叶节点包含了完整的数据记录。这种索引叫作汇集索引。由于InnoDB的数据文件自己要按主键汇集,因此InnoDB要求表必须有主键(MyISAM能够没有)性能
2). InnoDB的辅助索引优化
InnoDB的全部辅助索引都引用主键做为data域。例如,下图为定义在Col3上的一个辅助索引:
总结:
当经过辅助索引来查询数据时,须要进过两步:
首先,InnoDB 存储引擎会遍历辅助索引找到主键。
而后,再经过主键在汇集索引中找到完整的行记录数据。
面试题二、为何主键须要是自增 ID ,又或者为何主键须要带有时间性关联?
由于 插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,不然将会出现页分裂,严重影响性能。所以,对于 InnoDB 表,咱们通常都会定义一个自增的 ID 列为主键。
一、事务定义了四种事务隔离级别,不一样数据库在实现时,产生的并发问题是不一样的。
READ UNCOMMITTED(读未提交):事务中的修改,即便没有提交,对其余事务也都是可见的。
会致使脏读。
READ COMMITTED(读已提交):事务从开始直到提交以前,所作的任何修改对其余事务都是不可见的。
会致使不可重复读。
这个隔离级别,也能够叫作“不可重复读”。
REPEATABLE READ(可重复读):一个事务按相同的查询条件读取之前检索过的数据,其余事务插入了知足其查询条件的新数据。产生幻行。
会致使幻读。
SERIALIZABLE(可串行化):强制事务串行执行。
二、MySQL InnoDB 采用 MVCC 来支持高并发,实现结果以下表所示:
<X>
处,MySQL 由于其间隙锁的特性,致使其在可重复读的隔离级别下,不存在幻读问题。也就是说,上图 <X>
处,须要改为“否”!!!!SELECT xxx FROM t WHERE id = ? FOR UPDATE
的方式,得到到悲观锁,禁止其它事务操做对应的数据,从而解决幻读问题一、MySQL 的共享锁和排他锁,就是读锁和写锁。
二、表锁与行锁:由执行引擎决定
使用行锁或者表锁都是使用的悲观锁:SELECT ...... FOR UPDATE;
当查询有明确主键时使用的是行锁;查询无明确主键时使用表锁
三、悲观锁与乐观锁
乐观锁与悲观锁的实现机制?
- 悲观锁大多数状况下依靠数据库的锁机制实现,以保证操做最大程度的独占性。如:SELECT xxx FROM t WHERE id = ? FOR UPDATE 的方式
- 乐观锁,大可能是基于数据版本( Version )记录机制实现:乐观锁,实际就是经过版本号,从而实现 CAS 原子性更新。
四、死锁
死锁发生在当多个进程访问同一数据库时,其中每一个进程拥有的锁都是其余进程所需的,由此形成每一个进程都没法继续下去。简单的说,进程 A 等待进程 B 释放他的资源,B 又等待 A 释放他的资源,这样就互相等待就造成死锁。
下列方法有助于最大限度地下降死锁:
- 设置得到锁的超时时间。 经过超时,至少保证最差状况下,能够有退出的口子。
- 按同一顺序访问对象。 这个是最重要的方式。
- 避免事务中的用户交互。
- 保持事务简短并在一个批处理中。
- 使用低隔离级别。
- 使用绑定链接。
面试题:MySQL 中InnoDB引擎的行锁是经过加在什么上完成(或称实现)的?
InnoDB 是基于索引来完成行锁。
例如:SELECT * FROM tab_with_index WHERE id = 1 FOR UPDATE
FOR UPDATE 能够根据条件来完成行锁锁定,而且 id 是有索引键的列;若是 id 不是索引键,那么 InnoDB 将完成表锁,并发将无从谈起。
(1) SELECT
(2) DISTINCT <select_list>
(3) FROM <left_table>
(4) <join_type> JOIN <right_table>
(5) ON <join_condition>
(6) WHERE <where_condition>
(7) GROUP BY <group_by_list>
(8) HAVING <having_condition>
(9) ORDER BY <order_by_condition>
(10) LIMIT <limit_number>复制代码 |
多版本并发控制(MVCC),是一种用来解决读-写冲突的无锁并发控制,也就是为事务分配单向增加的时间戳,为每一个修改保存一个版本,版本与事务时间戳关联,读操做只读该事务开始前的数据库的快照。 这样在读操做不用阻塞写操做,写操做不用阻塞读操做的同时,避免了脏读和不可重复读。
参考:
一、https://www.cnblogs.com/nullzx/p/8729425.html
二、https://blog.csdn.net/bigtree_3721/article/details/73650601
三、http://svip.iocoder.cn/MySQL/Interview/