互联网公司面试必问的mysql题目(上)


介绍:MySQL是一个关系型数据库管理系统,目前属于 Oracle 旗下产品。虽然单机性能比不上oracle,但免费开源,单机成本低且借助于分布式集群所以受到互联网公司的青睐,是互联网公司的主流数据库。



01

什么是数据库事务?如果没有事物会有什么后果?事务的特性是什么?

事务是指作为单个逻辑工作单元执行的一系列操作,可以被看作一个单元的一系列SQL语句的集合。要么完全地执行,要么完全地不执行。

如果不对数据库进行并发控制,可能会产生 脏读、非重复读、幻像读、丢失修改的异常情况。

事务的特性(ACID)

A, atomacity 原子性 事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。通常,与某个事务关联的操作具有共同的目标,并且是相互依赖的。如果系统只执行这些操作的一个子集,则可能会破坏事务的总体目标。原子性消除了系统处理操作子集的可能性。

C, consistency 一致性

事务将数据库从一种一致状态转变为下一种一致状态。也就是说,事务在完成时,必须使所有的数据都保持一致状态(各种 constraint 不被破坏)。

I, isolation 隔离性 由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。换句话说,一个事务的影响在该事务提交前对其他事务都不可见。

D, durability 持久性

事务完成之后,它对于系统的影响是永久性的。该修改即使出现致命的系统故障也将一直保持。

“A向B汇钱100”

  1. 读出A账号余额(500)。

  2. A账号扣钱操作(500-100)。

  3. 结果写回A账号(400)。

  4. 读出B账号余额(500)。

  5. B账号做加法操作(500+100)。

  6. 结果写回B账号(600)。

原子性:

保证1-6所有过程要么都执行,要么都不执行。如果异常了那么回滚。

一致性

转账前,A和B的账户中共有500+500=1000元钱。转账后,A和B的账户中共有400+600=1000元。

隔离性

在A向B转账的整个过程中,只要事务还没有提交(commit),查询A账户和B账户的时候,两个账户里面的钱的数量都不会有变化。

持久性

一旦转账成功(事务提交),两个账户的里面的钱就会真的发生变化


02

什么是脏读?幻读?不可重复读?什么是事务的隔离级别?Mysql的默认隔离级别是?


  • 脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

  • 不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。

  • 幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。


Read uncommitted

读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据。

Read committed

读提交,顾名思义,就是一个事务要等另一个事务提交后才能读取数据。

小A去买东西(卡里有1万元),当他买单时(事务开启),系统事先检测到他的卡里有1万,就在这个时候!!小A的妻子要把钱全部转出充当家用,并提交。当系统准备扣款时,再检测卡里的金额,发现已经没钱了(第二次检测金额当然要等待妻子转出金额事务提交完)。A就会很郁闷


分析:这就是读提交,若有事务对数据进行更新(UPDATE)操作时,读操作事务要等待这个更新操作事务提交后才能读取数据,可以解决脏读问题。但在这个事例中,出现了一个事务范围内两个相同的查询却返回了不同数据,这就是不可重复读。



Repeatable read

重复读,就是在开始读取数据(事务开启)时,不再允许修改操作


事例:小A去买东西(卡里有1万元),当他买单时(事务开启,不允许其他事务的UPDATE修改操作),收费系统事先检测到他的卡里有1万。这时候他的妻子不能转出金额了。接下来收费系统就可以扣款了。


分析:重复读可以解决不可重复读问题。写到这里,应该明白的一点就是,不可重复读对应的是修改,即UPDATE操作。但是可能还会有幻读问题。因为幻读问题对应的是插入INSERT操作,而不是UPDATE操作。


什么时候会出现幻读?

事例:小A去买东西,花了2千元,然后他的妻子去查看他的消费记录(全表扫描FTS,妻事务开启),看到确实是花了2千元,就在这个时候,小A花了1万买了一部电脑,INSERT了一条消费记录,并提交。当妻子打印小A的消费记录清单时(妻子事务提交),发现花了1.2万元,似乎出现了幻觉,这就是幻读。


Serializable 序列化

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


Mysql的默认隔离级别是Repeatable read。



03

事物隔离是怎么实现的?


是基于锁实现的.

有哪些锁?分别介绍下

在DBMS中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎)、表级锁(MYISAM引擎)和页级锁(BDB引擎 )。

行级锁

行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大。行级锁分为共享锁 和 排他锁。

特点

开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

表级锁

表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MYISAM与INNODB都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)。

特点

开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。

页级锁

页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。

特点

开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般


04

什么是死锁?怎么解决?(前几问题是我个人最喜欢的连环炮,基本可以看出面试者的基础功)

死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对付的资源,从而导致恶性循环的现象。

常见的解决死锁的方法

1、如果不同程序会并发存取多个表,尽量约定以相同的顺序访问表,可以大大降低死锁机会。

2、在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率;

3、对于非常容易产生死锁的业务部分,可以尝试使用升级锁定颗粒度,通过表级锁定来减少死锁产生的概率;

如果业务处理不好可以用分布式事务锁或者使用乐观锁






05

SQL的生命周期?关键字的先后顺序?

  1. 应用服务器与数据库服务器建立一个连接

  2. 数据库进程拿到请求sql

  3. 解析并生成执行计划,执行

  4. 读取数据到内存并进行逻辑处理

  5. 通过步骤一的连接,发送结果到客户端

  6. 关掉连接,释放资源

1、 FROM:对 FROM 子句中的前两个表执行笛卡尔积(交叉联接),生成虚拟表 VT1。

2、 ON:对 VT1 应用 ON 筛选器,只有那些使为真才被插入到 TV2。
3、 OUTER (JOIN):如果指定了 OUTER JOIN(相对于 CROSS JOIN 或 INNER JOIN),保留表中未找到
匹配的行将作为外部行添加到 VT2,生成 TV3。如果 FROM 子句包含两个以上的表,则对上一个联接生成的
结果表和下一个表重复执行步骤 1 到步骤 3,直到处理完所有的表位置。
4、 WHERE:对 TV3 应用 WHERE 筛选器,只有使为 true 的行才插入 TV4。
5、 GROUP BY:按 GROUP BY 子句中的列列表对 TV4 中的行进行分组,生成 TV5。
6、 CUTE|ROLLUP:把超组插入 VT5,生成 VT6。
7、 HAVING:对 VT6 应用 HAVING 筛选器,只有使为 true 的组插入到 VT7。
8、 SELECT:处理 SELECT 列表,产生 VT8。
9、 DISTINCT:将重复的行从 VT8 中删除,产品 VT9。

10、 ORDER BY:将 VT9 中的行按 ORDER BY 子句中的列列表顺序,生成一个游标(VC10)。
11、 TOP:从 VC10 的开始处选择指定数量或比例的行,生成表 TV11,并返回给调用者。


06

什么是乐观锁?悲观锁?实现方式?

悲观锁

悲观锁指对数据被意外修改持保守态度,依赖数据库原生支持的锁机制来保证当前事务处理的安全性,防止其他并发事务对目标数据的破坏或破坏其他并发事务数据,将在事务开始执行前或执行中申请锁定,执行完后再释放锁定。这对于长事务来讲,可能会严重影响系统的并发处理能力。 自带的数据库事务就是典型的悲观锁。

乐观锁:

乐观锁(Optimistic Lock),顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。乐观锁适用于读多写少的应用场景,这样可以提高吞吐量。

一般是加一个版本号字段 每次更新时候比较版本号






07

大数据情况下如何做分页?

可以参考阿里巴巴java开发手册上的答案



08

什么是数据库连接池?

从上一个sql生命周期题目,可以看到其中的连接在里面发挥着重大作用,但频繁的创建和销毁,非常浪费系统资源。由于数据库更适合长连接,也就有个连接池,能对连接复用,维护连接对象、分配、管理、释放,也可以避免创建大量的连接对DB引发的各种问题;另外通过请求排队,也缓解对DB的冲击。




推荐阅读

专注Java知识分享!开源 Java 学习指南——JavaGuide(21k+ Star)的作者。公众号多篇文章被各大技术社区转载。欢迎关注!



如果喜欢本文的话,小伙伴们不要忘记给本文点个好看以及转发分享。



要回复问题请先登录注册