Mysql面试问题总结

 

Mysql引擎

 

InnoDB和MyISAM引擎区别

innodb默认的是行级锁,也支持表级锁,myisam只支持表级锁;

如果是事务型数据库,肯定首选innodb,因为innodb支持事务的提交和回滚;

innodb支持外键,myisam不支持;

如果表用于插入新记录和读出记录,myisam效率更高;

innodb是聚簇索引(叶子节点包含完整的行记录),myisam不是;

myisam的主次索引都指向物理行,innodb主索引(文件)的叶子节点直接存储数据,次索引指向对主键的引用

 

InnoDB和MyISAM引擎选择

MyISAM相对简单,效率更高,如果是读多写少的系统会比较合适,Innodb适合更新频繁的系统,适合高并发场景,适合原子性操作多的系统。

 

 

 

 

 

Mysql索引

 

索引为什么会使查询会变快

传统查询是需要按照表的顺序遍历的,添加完索引后,会有一个二叉树类型的索引文件,可以帮助我们提高查询速度

 

有哪些情况需要加索引

需要搜索的列上(加快查询速度);

作为主键或者外键的列上(加快连接速度);

经常需要排序的列上(因为索引已经排序);

需要进行范围搜索的列上(也是因为索引已经排序);

 

哪些情况不适合加索引

内容频繁变化的字段(增删改操作的时候,还要顺带维护索引文件,影响性能);

区分度不大的字段;

 

主键和唯一索引的区别

创建索引的语法不同;唯一索引可以有多个;主键不可以为空;

 

什么是聚簇索引、非聚簇索引

聚簇索引(聚集索引):索引的叶子节点包含了完整的数据记录;innodb主键索引保存数据行,次(辅助)索引叶子节点保存的是主键索引的值。

非聚簇索引(辅助索引):索引叶子节点保存的是数据行所在的地址,而不是数据行本身;非聚簇索引的情况下,主键索引和辅助索引基本没有区别。

 

聚簇索引和非聚簇索引的优劣势

聚簇索引:

优点:检索效率高,数据就在主键索引的叶节点下

缺点:会造成更新代价比较高,更新索引需要带着数据一起迁移(页分裂、页移动);

非聚簇索引(也叫二级索引):

优点:更新代价比较低

缺点:不能直达数据,可能要链式的访问多级页表,才能定位到数据

 

hash索引相比btree的优缺点

优点:检索效率非常高,索引的检索可以一步到位,而btree需要访问到叶节点

缺点:由于hash本身的特殊性,hash不适用于范围查询,不适用于数据的排序操作,如果存在大量重复元素的列作为索引,会导致大量的hash冲突,导致效率反而不及btree

 

为啥用b+tree而不用b-tree

b-tree所有的节点都存储数据,而b+tree只有叶子节点才存储数据,而内存每次加载数据的大小是有限的。这样一次查询能携带的关键字更多,使得b+tree的磁盘读写代价更低;

另外由于所有数据都存储在叶子节点,且有序,b+树更适合做区间查询(范围查询),而同样的情况,b-tree不支持或者效率太低。

 

B+树如何进行查询

通常在B+Tree上有两个头指针,一个指向根节点,另一个指向关键字最小的叶子节点,而且所有叶子节点(即数据节点)之间是一种链式环结构。因此可以对B+Tree进行两种查找运算:一种是对于主键的范围查找和分页查找,另一种是从根节点开始,进行随机查找。

 

mysql为何使用b+tree

Innodb存储引擎中页的大小为16KB,一般表的主键类型为4-8个字节,指针类型一般也为4-8个字节,也就是说一个页(B+Tree中的一个节点)中大概存储16KB/(8B+8B)=1K个键值。也就是说一个深度为3的B+Tree索引可以维护1k*1k*1k=10亿条记录。

实际情况中,每个节点不可能都填满,因此在数据库中,B+Tree的高度一般都在2-4层,mysql的Innodb存储引擎在设计时是将根节点常驻内存的,也就是说,查找某一键值的行记录时最多只需要1-3次磁盘I/O操作。

 

 

 

Mysql的几种连接方式

 

内连接

select * from a,b where a.c=b.c 等价于select * from a inner join b on a.c=b.c,返回的是两个数据集的交集;

 

左连接(左外连接)

select * from a left join b on a.c=b.c,将a表查询的结果去b中做匹配,匹配不到的就显示为null,所以返回的总数为表a中行数;

 

右连接(右外连接)

select * from a right join b on a.c=b.c 与上相反,将b表结果拿去和a做匹配,匹配不到为null,返回总行数为b表行数。

 

 

 

 

 

其他

 

如何开启查询缓存

set global  query_cache_type=1;

set global  query_cache_size=600000;

开启查询缓存后在同样的查询条件以及数据情况下,会直接在缓存中返回结果

 

 

 

 

 

事务

 

什么是数据库事务

事务是一系列操作,需要同时成功或者失败,需要符合ACID特性

 

ACID

原子性:要么全成功要么全失败,不可能只执行一部分操作;

一致性:数据库总是从一个一致性的状态,转移到另一个一致性的状态,不会存在中间状态;比如AB两人转账,AB账户加起来的金额开始的时候是1w,那事务结束的时候也应该是1w

隔离性:当有多个用户并发访问数据库时,比如操作数据库的同一张表,数据库为每个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

持久性:指一个事务一旦提交了,那么对数据库中数据的改变就是永久的,即便是在数据库系统遇到故障的情况下,也不会丢失提交事务的操作。

 

多事务的并发问题

脏读:

不可重复读:

幻读:

 

事务隔离级别

由低到高:

Read uncommitted:读未提交,就是一个事务可以读取另一个未提交事务的数据;可能会导致脏读;

Read committed:读提交,就是一个事务需要等到另一个事务提交以后才能读取数据;可能出现不可重复读;

Repeatable Read:重复读,就是开始读取数据(事务开启)时,不再允许修改操作,但可以进行Insert操作;可能出现幻读;

Serializable序列化:Serializable是最高的事务隔离级别,在该级别下,事务串行化处理,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。

 

控制隔离级别的字段

Show variables like 'tx_isolation';并设置,如果要在my.cnf文件中配置,就是配置transaction_isolation字段

 

Read uncommitted

读未提交

就是一个事务可以读取另一个未提交事务的数据

可能造成的问题:脏读,读取了另一个未提交的事物的数据

 

Read committed

读已提交

若有事务对数据进行更新操作时,读操作事务要等待这个更新操作事务提交后才能读取数据

可以解决的问题:脏读

可能造成的问题:不可重复读,由于修改了记录,一个事务范围内两个相同的查询却返回了不同的数据

 

Repeatable Read

重复读(Mysql默认)

开始读取数据(事务开启)时,不再允许修改操作,但可以进行Insert操作

可以解决的问题:不可重复读

可能造成的问题:幻读,由于其他事务进行了Insert操作,从而产生了隐藏行,当当前事务未指定条件而更新到隐藏行的时候,隐藏行就会现形。

 

Serializable序列化

隔离性最强,没有并发能力,事务全部串行化处理,不会出现脏读,不可重复读,幻读,效率低下一般不使用。

 

事物的隔离性是如何实现的

事务通过锁的机制满足隔离性

 

innodb的“一致性非锁定读”机制

“一致性非锁定读”表示,如果当前行被施加了排他锁,那当需要读取行数据时,则不会等待行上的锁释放,而是会直接去读取一个快照数据(在“可重读”隔离级别下,快照数据是指当前事务开始时数据的样子)。

事务1、2同时进行的时候,1对数据写操作(排他锁),这是2依旧可以正常的读取该数据,应为读物的是(事务2)快照数据,也就是历史数据,这种机制提高了数据库的并发性。

 

你可能感兴趣的:(面试,Mysql,面试,Mysql)