数据库常见面试题
Posted adai-study
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据库常见面试题相关的知识,希望对你有一定的参考价值。
1、数据库常见优化方案
- 对查询进行优化,要尽量避免全表扫描;
- 考虑在 where 及 order by 涉及的列上建立索引,
2、导致引擎放弃使用索引而进行全表扫描的情况
- 在 where 子句中对字段进行 null 值判断
- 在 where 子句中使用 != 或 <> 操作符
- 在 where 子句中使用 or 来连接条件,修改方案:使用union联合查询
- in和 not in 也要慎用,修改方案:对于连续的数值,能用 between就不要用 in 了,用 exists 代替 in 是一个好的选择
- 在 where子句中对字段进行表达式操作
- 在where子句中对字段进行函数操作
- 含前导模糊查询的Like语法,后导模糊查询会使用索引
3、MySQL锁机制
数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则。
mysql各存储引擎使用了三种类型(级别)的锁定机制:表级锁定,行级锁定和页级锁定。MySQL这3种锁的特性可大致归纳如下:
- 表级锁定:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低;
- 行级锁定:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高;
- 页级锁定:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
- 适用:从锁的角度来说,表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web应用;而行级锁则更适合于有大量按索引条件并发更新数据,同时又有并发查询的应用,如一些在线事务处理(OLTP)系统。
4、MySQL悲观锁和乐观锁
悲观锁与乐观锁是两种常见的资源并发锁设计思路,也是并发编程中一个非常基础的概念。
悲观锁的特点是先获取锁,再进行业务操作,即“悲观”的认为获取锁是非常有可能失败的,因此要先确保获取锁成功再进行业务操作。通常所说的“一锁二查三更新”即指的是使用悲观锁。通常来讲在数据库上的悲观锁需要数据库本身提供支持,即通过常用的select … for update操作来实现悲观锁。当数据库执行select for update时会获取被select中的数据行的行锁,因此其他并发执行的select for update如果试图选中同一行则会发生排斥(需要等待行锁被释放),因此达到锁的效果。select for update获取的行锁会在当前事务结束时自动释放,因此必须在事务中使用。mysql还有个问题是select for update语句执行中所有扫描过的行都会被锁上,这一点很容易造成问题。因此如果在mysql中用悲观锁务必要确定走了索引,而不是全表扫描。
乐观锁的特点是先进行业务操作,不到万不得已不去拿锁。即“乐观”的认为拿锁多半是会成功的,因此在进行完业务操作需要实际更新数据的最后一步再去拿一下锁就好。乐观锁是否在事务中其实都是无所谓的,其底层机制是:在数据库内部update同一行的时候是不允许并发的,即数据库每次执行一条update语句时会获取被update行的写锁,直到这一行被成功更新后才释放。因此在业务操作进行前获取需要锁的数据的当前版本号,然后实际更新数据时再次对比版本号确认与之前获取的相同,并更新版本号,即可确认这之间没有发生并发的修改。如果更新失败即可认为老版本的数据已经被并发修改掉而不存在了,此时认为获取锁失败,需要回滚整个业务操作并可根据需要重试整个过程。
- 乐观锁机制避免了长事务中的数据库加锁开销,大大提升了大并发量下的系统整体性能表现
- 乐观锁在不发生取锁失败的情况下开销比悲观锁小,但是一旦发生失败回滚开销则比较大,因此适合用在取锁失败概率比较小的场景,可以提升系统并发性能
- 乐观锁还适用于一些比较特殊的场景,例如在业务操作过程中无法和数据库保持连接等悲观锁无法适用的地方
- 在实际生产环境里边,如果并发量不大且不允许脏读,可以使用悲观锁解决并发问题;但如果系统的并发非常大的话,悲观锁定会带来非常大的性能问题,所以我们就要选择乐观锁定的方法.
以上是关于数据库常见面试题的主要内容,如果未能解决你的问题,请参考以下文章