MySQL 总结知识

本篇文章主要是整理一下mysql的基础知识 


1、mysql的执行引擎

  •  一、innodb: 默认的存储引擎是 InnoDB ,而且也是最主流的选择 

 支持事务。 
 支持行级锁和表级锁,能支持更多的并发量。 
 查询不加锁,彻底不影响查询。 
 支持崩溃后恢复。

  • 二、MyISAM:在 MySQL5.1 以及以前的版本,默认的存储引擎是 MyISAM ,可是目前已经再也不更新 

 不支持事务。 
 使用表级锁,若是数据量大,一个插入操做锁定表后,其余请求都将阻塞。 

2、索引

索引,都是实如今存储引擎层的。html

一、主要有六种类型:

一、普通索引:最基本的索引,没有任何约束。 
二、惟一索引:具备惟一性约束。 
三、主键索引:特殊的惟一索引,不容许有空值。
四、复合索引:将多个列组合在一块儿建立索引,能够覆盖多个列。 
五、外键索引:只有InnoDB类型的表才可使用外键索引,保证数据的一致性、完整性和实现级联操做。 
六、全文索引:MySQL 自带的全文索引只能用于 InnoDB、MyISAM ,而且只能对英文进行全文检索,通常使用全文索引引擎。(经常使用的全文索引引擎的解决方案有 Elasticsearch) 


二、MySQL 索引的“使用”注意事项? 

- 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+Tree 中,全部数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储 key 值信息,这样能够大大加大每一个节点存储的 key 值数量,下降 B+Tree 的高度。
  2. 一般在 B+Tree 上有两个头指针,一个指向根节点,另外一个指向关键字最小的叶子节点,并且全部叶子节点(即数据节点)之间是一种链式环结构。所以能够对 B+Tree 进行两种查找运算:一种是对于主键的范围查找和分页查找,另外一种是从根节点开始,进行随机查找。
  3. 在B-树基础上,为叶子结点增长链表指针,全部关键字都在叶子结点中出现,非叶子结点做为叶子结点的索引;B+树老是到叶子结点才命中;
面试题1:为何不用B树做为索引?
从 B-Tree 结构图中能够看到,每一个节点中不只包含数据的 key 值,还有 data 值。而每个页的存储空间是有限的,若是 data 数据较大时将会致使每一个节点(即一个页)能存储的 key 的数量很小,当存储的数据量很大时一样会致使 B-Tree 的深度较大,增大查询时的磁盘 I/O 次数,进而影响查询效率。在 B+Tree 中,全部数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储 key 值信息,这样能够大大加大每一个节点存储的 key 值数量,下降 B+Tree 的高度。


四、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 里,主键索引也被称为汇集索引(clustered index)。
  • 非主键索引的叶子节点存的数据是整行数据的主键,键值是索引。在 InnoDB 里,非主键索引也被称为辅助索引(secondary index)。  
  • 当经过辅助索引来查询数据时,须要进过两步:
           首先,InnoDB 存储引擎会遍历辅助索引找到主键。 
           而后,再经过主键在汇集索引中找到完整的行记录数据。
    面试题二、为何主键须要是自增 ID ,又或者为何主键须要带有时间性关联?
    由于 插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,不然将会出现页分裂,严重影响性能。所以,对于 InnoDB 表,咱们通常都会定义一个自增的 ID 列为主键。


    3、事务

    (一)、事务的特性  :指的是 ACID

    1. 原子性 Atomicity :一个事务(transaction)中的全部操做,或者所有完成,或者所有不完成,不会结束在中间某个环节。事务在执行过程当中发生错误,会被恢复(Rollback)到事务开始前的状态,就像这个事务历来没有执行过同样。即,事务不可分割、不可约简。
    2. 一致性 Consistency :在事务开始以前和事务结束之后,数据库的完整性没有被破坏。
    3. 隔离性 Isolation :数据库容许多个并发事务同时对其数据进行读写和修改的能力,隔离性能够防止多个事务并发执行时因为交叉执行而致使数据的不一致。事务隔离分为不一样级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
    4. 持久性 Durability :事务处理结束后,对数据的修改就是永久的,即使系统故障也不会丢失。

    (二)、事务的隔离级别

    一、事务定义了四种事务隔离级别,不一样数据库在实现时,产生的并发问题是不一样的。

    • READ UNCOMMITTED(读未提交):事务中的修改,即便没有提交,对其余事务也都是可见的。

      会致使脏读。

    • READ COMMITTED(读已提交):事务从开始直到提交以前,所作的任何修改对其余事务都是不可见的。

      会致使不可重复读。

      这个隔离级别,也能够叫作“不可重复读”。

    • REPEATABLE READ(可重复读):一个事务按相同的查询条件读取之前检索过的数据,其余事务插入了知足其查询条件的新数据。产生幻行。

      会致使幻读。

    • SERIALIZABLE(可串行化):强制事务串行执行。

    二、MySQL InnoDB 采用 MVCC 来支持高并发,实现结果以下表所示:


    • MySQL 默认的事务隔离级别为可重复读(repeatable-read) 。
    • 上图的 <X> 处,MySQL 由于其间隙锁的特性,致使其在可重复读的隔离级别下,不存在幻读问题。也就是说,上图 <X> 处,须要改为“否”!!!!
    • 有些资料说可重复读解决了幻读,实际是存在的,能够经过 SELECT xxx FROM t WHERE id = ? FOR UPDATE 的方式,得到到悲观锁,禁止其它事务操做对应的数据,从而解决幻读问题


    4、mysql锁机制

    一、MySQL 的共享锁和排他锁,就是读锁和写锁。

    二、表锁与行锁:由执行引擎决定

    使用行锁或者表锁都是使用的悲观锁:SELECT ...... FOR UPDATE;

    当查询有明确主键时使用的是行锁;查询无明确主键时使用表锁

    • 表锁:系统开销最小,会锁定整张表,MyIsam 使用表锁。
    • 行锁:最大程度的支持并发处理,可是也带来了最大的锁开销,InnoDB 使用行锁。

    三、悲观锁与乐观锁

    • 乐观锁:能够读,不能写 
    • 悲观锁:不能读写,就是上面看到的共享锁和排他锁

    乐观锁与悲观锁的实现机制?
    • 悲观锁大多数状况下依靠数据库的锁机制实现,以保证操做最大程度的独占性。如: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 将完成表锁,并发将无从谈起。

    5、MySQL 查询执行顺序

    (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>复制代码

    6、什么是 MVCC

    多版本并发控制(MVCC),是一种用来解决读-写冲突的无锁并发控制,也就是为事务分配单向增加的时间戳,为每一个修改保存一个版本,版本与事务时间戳关联,读操做只读该事务开始前的数据库的快照。 这样在读操做不用阻塞写操做,写操做不用阻塞读操做的同时,避免了脏读和不可重复读。

    7、MySQL SQL 优化





    参考:

    一、https://www.cnblogs.com/nullzx/p/8729425.html

    二、https://blog.csdn.net/bigtree_3721/article/details/73650601

    三、http://svip.iocoder.cn/MySQL/Interview/

    相关文章
    相关标签/搜索