Mysql常见面试题整理

1.Mysql 的存储引擎有哪些?,Myisam 引擎与Innodb 引擎的区别是什么?

存储引擎说白了就是如何存储数据、如何为存储的数据建立索引和如何更新、查询数据等技术的实现方法。
Mysiam ,Innodb,Memory,Merge 等

区别
Innodb 支持事物,而myisam 不支持事物,
myisam 用于多查询及插入为主的应用,而innodb 适合频繁修改的以及设计到安全新较高的应用。
myisam 支持表锁,innodb支持行锁,Innodb 是需要指定的,支持外键,不支持FULLTEXT 类型的索引。
myisam不支持外键,清空表时,Innodb 是一行行的删,而myisam 会重建表

2.三范式指的是哪三范式?

第一范式(1NF)
强调的是列的原子性,即列不能够再分成其他几列。
考虑这样一个表:【联系人】(姓名,性别,电话)
如果在实际场景中,一个联系人有家庭电话和公司电话,那么这种表结构设计就没有达到 1NF。要符合 1NF 我们只需把列(电话)拆分,即:【联系人】(姓名,性别,家庭电话,公司电话)。1NF 很好辨别,但是 2NF 和 3NF 就容易搞混淆。

第二范式(2NF)

第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。另外包含两部分内容,一是表必须有一个主键;二是没有包含在主键中的列必须完全依赖于主键,而不能只依赖于主键的一部分。

考虑一个订单明细表:【OrderDetail】(OrderID,ProductID,UnitPrice,Discount,Quantity,ProductName)。

因为我们知道在一个订单中可以订购多种产品,所以单单一个 OrderID 是不足以成为主键的,主键应该是(OrderID,ProductID)。显而易见 Discount(折扣),Quantity(数量)完全依赖(取决)于主键(OderID,ProductID),而 UnitPrice,ProductName 只依赖于 ProductID。所以 OrderDetail 表不符合 2NF。不符合 2NF 的设计容易产生冗余数据。

可以把【OrderDetail】表拆分为【OrderDetail】(OrderID,ProductID,Discount,Quantity)和【Product】(ProductID,UnitPrice,ProductName)来消除原订单表中UnitPrice,ProductName多次重复的情况。

第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。简而言之,第二范式就是在第一范式的基础上属性完全依赖于主键。

第三范式(3NF)

在1NF基础上,任何非主属性不依赖于其它非主属性[在2NF基础上消除传递依赖]。
满足第三范式(3NF)肯定是 2NF,另外非主键列必须直接依赖于主键,不能存在传递依赖。即不能存在:非主键列 A 依赖于非主键列 B,非主键列 B 依赖于主键的情况。

考虑一个订单表【Order】(OrderID,OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity)主键是(OrderID)。
其中 OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity 等非主键列都完全依赖于主键(OrderID),所以符合 2NF。不过问题是 CustomerName,CustomerAddr,CustomerCity 直接依赖的是 CustomerID(非主键列),而不是直接依赖于主键,它是通过传递才依赖于主键,所以不符合 3NF。
通过拆分【Order】为【Order】(OrderID,OrderDate,CustomerID)和【Customer】(CustomerID,CustomerName,CustomerAddr,CustomerCity)从而达到 3NF。

第二范式(2NF)和第三范式(3NF)的概念很容易混淆,区分它们的关键点在于,2NF:非主键列是否完全依赖于主键,还是依赖于主键的一部分;3NF:非主键列是直接依赖于主键,还是直接依赖于非主键列。

3.什么是事物?有那些特征?事物的隔离级别有那些?mysql的默认隔离级别有哪些?

事务(Transaction)是并发控制的基本单位。所谓的事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。事务是数据库维护数据一致性的单位,在每个事务结束时,都能保持数据一致性。

事物的四个特征(ACID)

A(Atomicity)原子性: 在一个事务上下文里面,对数据库进行的任何操作,必须保证是原子的,也就是说要么不做,要么全部都做,不能只做一部分;

C(Consistency) 一致性:执行事务前后,保证数据一致,多个事务对同一个数据读取的结果是相同的;

I(Isolation)隔离性:并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;

D(Durability)持久性:事务一旦提交,在事务中对数据库进行的修改也就进行持久化存储了,不会由于系统故障导致提交后的数据丢失。

SQL标准定义了四个隔离级别:

**READ-UNCOMMITTED(读未提交):**最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。

**READ-COMMITTED(读已提交):**允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读和不可重复读仍有可能发生。

**REPEATABLE-READ(可重复读):**对同一字段的多次读取结果都是一致的,除非数据是被本身事务所修改,可以阻止脏读和不可重复读,但是幻读仍有可能发生。

**SERIALIZABLE(可串行化):**最高的隔离级别,完全服从ACID的隔离级别,所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以阻止脏读、幻读和不可重复读。

MySQL InnoDB存储引擎的默认支持的隔离级别是REPEATABLE-READ(可重复复读),在分布式事务的情况下,一般会用到SERIALIZABLE(可串行化)隔离级别。

4.脏读、幻读、不可重复读、丢失修改指的是什么?

脏读: 事务A查询数据后进行了一次修改且未提交,而事务B这个时候去查询,然后使用了这个数据,因为这个数据还没有被事务A 提交到数据库中,所以事务B的得到数据就是脏数据,对脏数据进行操作可能是不正确的。

不可重复读: 事务A访问了两次数据,但是这访问第二次之间事务B进行一次并进行了修改,导致事务A访问第二次的时候得到的数据与第一次不同,导致一个事务访问两次数据得到的数据不相同。因此叫做不可重复读。

幻读: 与不可重复读都点相似,只是这次是事务B在事务A访问第二次的之前做了一个新增,导致事务A第二次读取的时候发现了多的记录,这就是幻读。

**丢失修改:**事务A访问该数据,事务B也访问该数据,事务A修改了该数据,事务B也修改了该数据,这样导致事务A的修改被丢失,因此称为丢失修改;

不可重复度和幻读区别:

不可重复读主要是修改操作,幻读的主要在于新增或者删除。

幻读主要在于数据的条数变了,而不可重复读主要在于数据内容变了。

5.数据库优化 ([索引相关](https://blog.csdn.net/JMW1407/article/details/107753326?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161534755216780262519828%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=161534755216780262519828&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_v2~rank_v29-1-107753326.first_rank_v2_pc_rank_v29&utm_term=.%E6%95%B0%E6%8D%AE%E5%BA%93%E4%BC%98%E5%8C%96%20%20%20%20%20%20%20%205.1%20%E4%BB%80%E4%B9%88%E6%98%AF%E6%95%B0%E6%8D%AE%E5%BA%93%E7%B4%A2%E5%BC%95%EF%BC%9F%E6%95%B0%E6%8D%AE%E5%BA%93%E7%B4%A2%E5%BC%95%E6%9C%89%E5%93%AA%E4%BA%9B%E7%B1%BB%E5%9E%8B%EF%BC%9F%20%20%20%20%20%20%20%205.2%20%E6%95%B0%E6%8D%AE%E5%BA%93%E7%B4%A2%E5%BC%95b%2btree%E7%9A%84%E7%90%86%E8%A7%A3%EF%BC%9F%20%20%20%20%20%20%20%205.3%20%E8%81%9A%E9%9B%86%E7%B4%A2%E5%BC%95%E4%B8%8E%E9%9D%9E%E8%81%9A%E9%9B%86%E7%B4%A2%E5%BC%95%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB?%20%20%20%20%20%20%20%205.4%20%E5%B7%A5%E4%BD%9C%E4%B8%AD%E5%A6%82%E4%BD%95%E8%BF%9B%E8%A1%8C%E6%95%B0%E6%8D%AE%E5%BA%93%E4%BC%98%E5%8C%96%EF%BC%9F%E5%88%97%E4%B8%BE%E7%B4%A2%E5%BC%95%E5%A4%B1%E6%95%88%E7%9A%84%E5%9C%BA%E6%99%AF))

5.1 什么是数据库索引?数据库索引有哪些类型?

  • 索引是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址。
  • 索引是一种数据结构。数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B+树。
  • 索引就相当于目录。为了方便查找书中的内容,通过对内容建立索引形成目录。
  • 索引是一个文件,它是要占据物理空间的。

从功能上说,索引分为 6 种:普通索引,唯一索引,主键索引,复合索引,外键索引,全文索引。

  • 1、普通索引:最基本的索引,没有任何约束。
ALTER TABLE 'table_name' ADD INDEX ('column')
  • 2、唯一索引:与普通索引类似,但具有唯一性约束。在表上一个或者多个字段组合建立的索引,这个(或这几个)字段的值组合起来在表中不可以重复。一张表可以建立任意多个唯一索引,但一般只建立一个。
ALTER TABLE 'table_name' ADD UNIQUE('column')
  • 3、主键索引:特殊的唯一索引,不允许有空值。
    唯一索引列允许null值,而主键列不允许为null值。一张表最多建立一个主键,也可以不建立主键。
ALTER TABLE 'table_name' ADD PRIMARY KEY('column')
  • 4、复合索引:将多个列组合在一起创建索引,可以覆盖多个列。
    姓 - 名 - 电话号码。电话簿中的内容先按照姓氏的拼音排序,相同姓氏再按名字的拼音排序,这相当于在(姓,名)上建立了一个复合索引。
ALTER TABLE 'table_name' ADD INDEX('colimn1','column2')

5、外键索引:只有InnoDB类型的表才可以使用外键索引,保证数据的一致性、完整性和实现级联操作。

6、全文索引:MySQL 自带的全文索引只能用于 InnoDB、MyISAM,并且只能对英文进行全文检索,一般使用全文索引引擎(ES,Solr)。

ALTER TABLE 'table_name' ADD FULLTEXT('column')

注意:主键就是唯一索引,但是唯一索引不一定是主键,唯一索引可以为空,但是空值只能有一个,主键不能为空

5.2 数据库索引b+tree的理解?

5.3 聚集索引与非聚集索引有什么区别?

聚簇索引(InnoDB)
辅助索引的叶子节点的data存储的是主键的值;
主索引的叶子节点的data存储的是数据本身,也就是说数据和索引存储在一起;
索引查询到的地方就是数据(data)本身,那么索引的顺序和数据本身的顺序就是相同的;

非聚簇索引(MyISAM )
主索引和辅助索引的叶子节点的data都是存储的数据的物理地址,也就是说索引和数据并不是存储在一起的,数据的顺序和索引的顺序并没有任何关系,也就是索引顺序与数据物理排列顺序无关。

5.4 索引的使用策略

5.4.1、什么时候要使用索引?

  • 1、主键自动建立唯一索引;
  • 2、经常作为查询条件在WHERE或者ORDER BY 语句中出现的列要建立索引;
  • 3、作为排序的列要建立索引;
  • 4、查询中与其他表关联的字段,外键关系建立索引
  • 5、高并发条件下倾向组合索引;
  • 6、用于聚合函数的列可以建立索引,例如使用了max(column_1)或者count(column_1)时的column_1就需要建立索引

5.4.2、什么时候不要使用索引?

  • 1、经常增删改的列不要建立索引;
  • 2、有大量重复的列不建立索引;
  • 3、表记录太少不要建立索引。

7.3、索引失效的情况?

  • 1、在组合索引中不能有列的值为NULL,如果有,那么这一列对组合索引就是无效的。
  • 2、在一个SELECT语句中,索引只能使用一次,如果在WHERE中使用了,那么在ORDER BY中就不要用了。
  • 3、LIKE操作中,’%aaa%'不会使用索引,也就是索引会失效,但是‘aaa%’可以使用索引。
  • 4、在索引的列上使用表达式或者函数会使索引失效
    例如:select * from users where YEAR(adddate) < 2007,这将导致索引失效而进行全表扫描
  • 5、在查询条件中使用IS NULL或者IS NOT NULL会导致索引失效。
  • 6、字符串不加单引号会导致索引失效。更准确的说是类型不一致会导致失效,
    比如字段email是字符串类型的,使用WHERE email=99999 则会导致失败,应该改为WHERE email=‘99999’。
  • 7、在查询条件中使用OR连接多个条件会导致索引失效,除非OR链接的每个条件都加上索引,这时应该改为两次查询,然后用UNION ALL连接起来。
  • 8、如果排序的字段使用了索引,那么select的字段也要是索引字段,否则索引失效。

6.数据库锁机制了解么?实际开发中有遇到死锁的情况么?

  • 锁是事务对某个数据库中的资源(如表和记 录)存取前,先向系统提出请求,封锁该资源,
  • 事务获得锁后,即取得对数据的控制权,在事务释放它的锁之前,其他事务不能更新此数据。当事务撤消后,释放被锁定的资源。

数据库锁的分类:

  • 共享锁:又叫S锁或者读锁,加了共享锁的数据对象可以被其他事务读取,但不能修改,通常是该数据对象被读取完毕,锁立即被释放
  • 排他锁:又叫X锁或者写锁,当数据对象被加上排它锁时,一个事务必须得到锁才能对该数据对象进行访问,一直到事务结束锁才被释放。 在此之间其他的事 务不能对它读取和修改。

死锁:

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。
这些永远在互相等待的进程称为死锁进程

产生死锁的必要条件:

  • 1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
  • 2、不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
  • 3、请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
  • 4、循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。

如何避免死锁

三种用于避免死锁的技术:

1)加锁顺序:

一个线程需要一些锁,那么它必须按照确定的顺序获取锁。它只有获得了从顺序上排在前面的锁之后,才能获取后面的锁。

例如,线程2和线程3只有在获取了锁A之后才能尝试获取锁C(获取锁A是获取锁C的必要条件)。因为线程1已经拥有了锁A,

所以线程2和3需要一直等到锁A被释放。然后在它们尝试对B或C加锁之前,必须成功地对A加了锁。

2)加锁时限 :

另外一个可以避免死锁的方法是在尝试获取锁的时候加一个超时时间,这也就意味着在尝试获取锁的过程中若超过了这个时限该线程则放弃对该锁请求。

并会进行回退并释放所有已经获得的锁,然后等待一段随机的时间再重试。这段随机的等待时间让其它线程有机会尝试获取相同的这些锁,

并且让该应用在没有获得锁的时候可以继续运行(加锁超时后可以先继续运行干点其它事情,再回头来重复之前加锁的逻辑)。

3)死锁检测:

每当一个线程获得了锁,会在线程和锁相关的数据结构中(map、graph等等)将其记下。除此之外,每当有线程请求锁,也需要记录在这个数据结构中。

当一个线程请求锁失败时,这个线程可以遍历锁的关系图看看是否有死锁发生。如果检测到死锁,就释放所有锁,回退,并且等待一段随机的时间后再重试

遇到死锁怎么办?

我们先了解下死锁定理:
①如果资源分配图中没有环路,则系统没有死锁;
②如果资源分配图中出现了环路,则系统可能有死锁。

从上面的死锁定理中我们可以知道只要打破死锁的环路就可以解开死锁,以下是处理死锁的两种名方法:

1)抢占资源:挂起某些死锁进程,并抢占它的资源,将这些资源分配给其他的死锁进程。但应防止被挂起的进程长时间得不到资源,而处于资源匮乏的状态。

2)终止(或撤销)进程:终止或撤销系统中的一个或多个死锁进程,直至打破死锁状态

7、MySQL中varchar与char的区别以及varchar(50)中的50代表的涵义

(1)、varchar与char的区别 char是一种固定长度的类型,varchar则是一种可变长度的类型
(2)、varchar(50)中50的涵义
最多存放50个字符,varchar(50)和(200)存储hello所占空间一样,但后者在排序时会消耗更多内存,因为order by
col采用fixed_length计算col长度(memory引擎也一样)
(3)、int(20)中20的涵义 是指显示字符的长度,但要加参数的,最大为255,比如它是记录行数的id,插入10笔资料,它就显示00000000001 ~~~00000000010,当字符的位数超过11,它也只显示11位,如果你没有加那个让它未满11位就前面加0的参数,它不会在前面加0, 20表示最大显示宽度为20,但仍占4字节存储,存储范围不变;
(4)、mysql为什么这么设计
对大多数应用没有意义,只是规定一些工具用来显示字符的个数;int(1)和int(20)存储和计算均一样;

8、简单说一说drop、delete与truncate的区别

SQL中的drop、delete、truncate都表示删除,但是三者有一些差别

1、delete和truncate只删除表的数据不删除表的结构
2、速度,一般来说: drop> truncate >delete
3、delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效;
4、如果有相应的trigger,执行的时候将被触发. truncate,drop是ddl, 操作立即生效,原数据不放到rollback
segment中,不能回滚. 操作不触发trigger.

9、drop、delete与truncate分别在什么场景之下使用?

1、不再需要一张表的时候,用drop
2、想删除部分数据行时候,用delete,并且带上where子句
3、保留表而删除所有数据的时候用truncate

10、超键、候选键、主键、外键分别是什么?

1、超键:在关系中能唯一标识元组的属性集称为关系模式的超键。一个属性可以为作为一个超键,多个属性组合在一起也可以作为一个超键。超键包含候选键和主键。
2、候选键:是最小超键,即没有冗余元素的超键。
3、主键:数据库表中对储存数据对象予以唯一和完整标识的数据列或属性的组合。一个数据列只能有一个主键,且主键的取值不能缺失,即不能为空值(Null)。
4、外键:在一个表中存在的另一个表的主键称此表的外键。

11、什么是视图?以及视图的使用场景有哪些?

  • 1、视图是一种虚拟的表,具有和物理表相同的功能。可以对视图进行增,改,查,操作,试图通常是有一个表或者多个表的行或列的子集。对视图的修改不影响基本表。它使得我们获取数据更容易,相比多表查询。
  • 2、只暴露部分字段给访问者,所以就建一个虚表,就是视图。
  • 3、查询的数据来源于不同的表,而查询者希望以统一的方式查询,这样也可以建立一个视图,把多个表查询结果联合起来,查询者只需要直接从视图中获取数据,不必考虑数据来源于不同表所带来的差异

猜你喜欢

转载自blog.csdn.net/jingli456/article/details/114629943