数据库面试相关

参考:https://juejin.im/post/5a9ca0d6518825555c1d1acd#heading-10

目录

1. MySQL的语句执行顺序

2. 数据库的乐观锁和悲观锁是什么?

3. SQL 约束有哪几种?(列属性-列约束)

4. 数据库锁

5. Mysql存储引擎

6. 最左匹配原则


 

1. MySQL的语句执行顺序

MySQL的语句一共分为11步,如下图所标注的那样,最先执行的总是FROM操作最后执行的是LIMIT操作。其中每一个操作都会产生一张虚拟的表,这个虚拟的表作为一个处理的输入,只是这些虚拟的表对用户来说是透明的,但是只有最后一个虚拟的表才会被作为结果返回。如果没有在语句中指定某一个子句,那么将会跳过相应的步骤。

下面我们来具体分析一下查询处理的每一个阶段

  1. FORM: 对FROM的左边的表和右边的表计算笛卡尔积。产生虚表VT1

  2. ON: 对虚表VT1进行ON筛选,只有那些符合<join-condition>的行才会被记录在虚表VT2中。
  3. JOIN: 如果指定了OUTER JOIN(比如left join、 right join),那么保留表中未匹配的行就会作为外部行添加到虚拟表VT2中,产生虚拟表VT3, rug from子句中包含两个以上的表的话,那么就会对上一个join连接产生的结果VT3和下一个表重复执行步骤1~3这三个步骤,一直到处理完所有的表为止。
  4. WHERE: 对虚拟表VT3进行WHERE条件过滤。只有符合<where-condition>的记录才会被插入到虚拟表VT4中。
  5. GROUP BY: 根据group by子句中的列,对VT4中的记录进行分组操作,产生VT5.
  6. CUBE | ROLLUP: 对表VT5进行cube或者rollup操作,产生表VT6.
  7. HAVING: 对虚拟表VT6应用having过滤,只有符合<having-condition>的记录才会被 插入到虚拟表VT7中。
  8. SELECT: 执行select操作,选择指定的列,插入到虚拟表VT8中。
  9. DISTINCT: 对VT8中的记录进行去重。产生虚拟表VT9.
  10. ORDER BY: 将虚拟表VT9中的记录按照<order_by_list>进行排序操作,产生虚拟表VT10.
  11. LIMIT:取出指定行的记录,产生虚拟表VT11, 并将结果返回。

转自:https://www.cnblogs.com/rollenholt/p/3776923.html

 

2. 数据库的乐观锁和悲观锁是什么?

数据的锁定分为两种,第一种叫作悲观锁,第二种叫作乐观锁。

  1. 悲观锁:在多个事务同时存取数据库中同一数据时,对数据的冲突采取一种悲观的态度,也就是说假设数据肯定会冲突,所以在数据开始读取的时候就把数据锁定住。【数据锁定:数据将暂时不会得到修改】
  2. 乐观锁:认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让用户返回错误的信息。让用户决定如何去做。

实现

一、悲观锁
    1、排它锁,当事务在操作数据时把这部分数据进行锁定,直到操作完毕后再解锁,其他事务操作才可操作该部分数据。这将防止其他进程读取或修改表中的数据。
    2、实现:大多数情况下依靠数据库的锁机制实现

     一般使用 select ...for update 对所选择的数据进行加锁处理,例如select * from account where name=”Max” for update, 这条sql 语句锁定了account 表中所有符合检索条件(name=”Max”)的记录。本次事务提交之前(事务提交时会释放事务过程中的锁),外界无法修改这些记录。

二、乐观锁
    1、如果有人在你之前更新了,你的更新应当是被拒绝的,可以让用户重新操作。
    2、实现:使用version版本或者时间戳

     具体可通过给表加一个版本号或时间戳字段实现,当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值加一。当我们提交更新的时候,判断当前版本信息与第一次取出来的版本值大小,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则认为是过期数据,拒绝更新,让用户重新操作。

 

3. SQL 约束有哪几种?(列属性-列约束)

  1. PRIMARY KEY: 能唯一标识记录的字段,可以作为主键,在一个表只允许出现一个。
  2. UNIQUE: 控件字段内容不能重复,一个表允许有多个 Unique 约束。
  3. NULL:null不是数据类型,是列的一个属性。表示当前列是否可以为null,表示什么都没有。
    • null, 允许为空。默认。
    • not null, 不允许为空。
  4. DEFAULT:默认值属性
  5. AUTO_INCREMENT:自动增长约束
  6. COMMENT:注释
  7. FOREIGN KEY: 用于预防破坏表之间连接的动作,也能防止非法数据插入外键列,因为它必须是它指向的那个表中的值之一。

4. 数据库锁

参看:数据库两大神器【索引和锁】

 

  • 表锁
    • 开销小,加锁快;不会出现死锁;锁定力度大,发生锁冲突概率高,并发度最低
  • 行锁
    • 开销大,加锁慢;会出现死锁;锁定粒度小,发生锁冲突的概率低,并发度高

不同的存储引擎支持的锁粒度是不一样的:

  • InnoDB:行锁和表锁都支持

InnoDB只有通过索引条件检索数据才使用行级锁,否则,InnoDB将使用表锁

也就是说,InnoDB的行锁是基于索引的

  • MyISAM:只支持表锁

表锁

表锁下又分为两种模式

  • 表读锁(Table Read Lock)
  • 表写锁(Table Write Lock)

在表读锁和表写锁的环境下:读读不阻塞,读写阻塞,写写阻塞

  • 读读不阻塞:当前用户在读数据,其他的用户也在读数据,不会加锁
  • 读写阻塞:当前用户在读数据,其他的用户不能修改当前用户读的数据,会加锁!
  • 写写阻塞:当前用户在修改数据,其他的用户不能修改当前用户正在修改的数据,会加锁!

行锁:

我们使用Mysql一般是使用InnoDB存储引擎的。InnoDB和MyISAM有两个本质的区别:

  • InnoDB支持行锁
  • InnoDB支持事务

从上面也说了:我们是很少手动加表锁的。表锁对我们程序员来说几乎是透明的,即使InnoDB不走索引,加的表锁也是自动的

InnoDB实现了以下两种类型的行锁。

  • 共享锁(S锁):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
    • 也叫做读锁:读锁是共享的,多个客户可以同时读取同一个资源,但不允许其他客户修改
  • 排他锁(X锁):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。
    • 也叫做写锁:写锁是排他的,写锁会阻塞其他的写锁和读锁

为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁

  • 意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
  • 意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。
  • 意向锁也是数据库隐式帮我们做了,不需要程序员操心

 

5. Mysql存储引擎

常用的存储引擎有以下:

  • Innodb引擎,Innodb引擎提供了对数据库ACID事务的支持。并且还提供了行级锁外键的约束。它的设计的目标就是处理大数据容量的数据库系统。
  • MyIASM引擎(原本Mysql的默认引擎),不提供事务的支持,也不支持行级锁和外键

同一个数据库也可以使用多种存储引擎的表。如果一个表修改要求比较高的事务处理,可以选择InnoDB。这个数据库中可以将查询要求比较高的表选择MyISAM存储。如果该数据库需要一个用于查询的临时表,可以选择MEMORY存储引擎

 

6. 最左匹配原则

1.简单说下什么是最左匹配原则

顾名思义:最左优先,以最左边的为起点任何连续的索引都能匹配上。同时遇到范围查询(>、<、between、like)就会停止匹配(不实用索引)。

例如:b = 2 如果建立(a,b)顺序的索引,是匹配不到(a,b)索引的;但是如果查询条件是a = 1 and b = 2或者a=1(又或者是b = 2 and b = 1)就可以,因为优化器会自动调整a,b的顺序。再比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)顺序的索引,d是用不到索引的,因为c字段是一个范围查询,它之后的字段会停止匹配。

2.最左匹配原则的原理

最左匹配原则都是针对联合索引来说的,所以我们有必要了解一下联合索引的原理。了解了联合索引,那么为什么会有最左匹配原则这种说法也就理解了。

我们都知道索引的底层是一颗B+树,那么联合索引当然还是一颗B+树,只不过联合索引的健值数量不是一个,而是多个构建一颗B+树只能根据一个值来构建,因此数据库依据联合索引最左的字段来构建B+树

例子:假如创建一个(a,b)的联合索引,那么它的索引树是这样的


可以看到a的值是有顺序的,1,1,2,2,3,3,而b的值是没有顺序的1,2,1,4,1,2。所以b = 2这种查询条件没有办法利用索引,因为联合索引首先是按a排序的,b是无序的。

同时我们还可以发现在a值相等的情况下,b值又是按顺序排列的,但是这种顺序是相对的。所以最左匹配原则遇上范围查询就会停止,剩下的字段都无法使用索引。例如a = 1 and b = 2 a,b字段都可以使用索引,因为在a值确定的情况下b是相对有序的,而a>1and b=2,a字段可以匹配上索引,但b值不可以,因为a的值是一个范围,在这个范围中b是无序的。

 

7. Mysql实现full join

è¿éåå¾çæè¿°

oracle里面有full join,但是在mysql中没有full join。我们可以使用union来达到目的。

mysql> select * from t1 left join t2 on t1.id = t2.id
    -> union 
    -> select * from t1 right join t2 on t1.id = t2.id;

è¿éåå¾çæè¿°

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章