数据库面经(笔记)

数据库面经,续更

1.ACID事务四大特性

数据库事务:事务是并发控制的基本单位。
所谓的事务,它是一个操作序列,由一条或多条sql语句组成。

原子性,隔离性,一致性,持久性

原子性:事务开始后的所有操作,要么全部做完,要么全部不做,不可能停留在中间环节,当执行过程中出错,事务会回滚到事务开始前的阶段,所有的操作就像没发生过一样,也就是说,事务是一个不可分割的整体。

一致性:事务操作前和操作后,数据满足完整性约束,数据库保持一致性状态。

隔离性:在并发环境下,事务之间是相互隔离的,一个事务的执行不能被其他事务干扰,每个事务都有自己的完整空间。

持久性:事务处理结束后,对数据的修改是永久的,即使系统故障也不会丢失。


2.InnoDB引擎是怎么保证事务的四个特性的?

  • 持久性是通过 redo log (重做日志)来保证的;

  • 原子性是通过 undo log(回滚日志) 来保证的;

  • 隔离性是通过 MVCC(多版本并发控制) 或锁机制来保证的;

  • 一致性则是通过持久性+原子性+隔离性来保证;

3.数据库的三大范式

  • 第一范式1NF:数据库表字段不能在被分割,满足原子性。

  • 第二范式2NF:满足第一范式,非主键必须完全依赖于主键列,不能只依赖于主键的一部分。

  • 第三范式3NF:满足第二范式,非主键必须直接依赖于主键,不能存在间接依赖。

4.并发事务会引发什么问题?

1.脏读

一个事务读到未提交事务修改过的数据,就意味着发生了脏读现象。事务A读取了事务B更新的数据,然后B回滚操作,那么事务A读到的就是B的脏数据。

2.不可重复读

在一个事务内多次读取同一个数据,前后读到的数据是不一致的,这种现象就称为不可重复读。事务A多次读取同一数据,事务B在事务A读取的过程中,对数据做了更新并提交,导致事务A多次读取同一数据时,结果不一致。

3.幻读

事务A已经更改了表中的所有数据,但事务B又在表中插入一条数据,事务A发现还有一条数据没有更改过来,就跟发生了幻觉了,称为幻读。进行模糊查询,得到结果个数不一致。


5.事务的隔离等级

1.读未提交

一个事务还没提交,他做的变更就能被其他事务看到。

2.读提交

一个事务提交之后,他的变更才能被其他事务看到。

在InnoDB存储引擎中它是通过MVCC实现的,在每次查询前都会重新生成一个Read View。

3.可重复读

一个事务执行过程中看到的数据,跟事务刚启动时看到的数据时一致的,MySQL InnoDB引擎默认的隔离级别。在InnoDB存储引擎中它也是通过MVCC实现的,是在执行第一个查询语句前生成一个Read View,此后事务都一直用这个Read View。

4.串行化

会给记录加上读写锁,当多个事务对同一条记录进行读写操作时,如果发生了读写冲突,后访问的事务必须等前一个事务执行完成,才能继续执行。


6.数据库有哪些锁?

数据库InnoDB引擎主要有三种锁
Record lock(记录锁):单个行记录上的锁
Gap lock(间隙锁):间隙锁,锁定一个范围,不包括记录本身
next-key lock(record+gap):record+gap锁定一个范围,包括记录本身

全局锁

执行后,整个数据库就处于只读的状态了,这时对数据的增删改操作表的结构的更改操作,都会被阻塞。
全局锁一般用于全库逻辑备份。


表级锁

分为共享锁排他锁
当给表加上共享锁时,本线程和其他线程都只能对该表进行查询操作,其他操作都会阻塞;
当给表加上排他锁时,本线程可以对该表进行增删改操作,其他线程的所有操作都会被阻塞;

一般只有MyISAM引擎会用表锁,InnoDB引擎有更细粒度的行。

意向锁

意向共享锁和意向排他锁都是表级锁,不会和行级的共享锁和排他锁冲突,彼此之间也不会冲突,只会跟表级别的共享锁和排他锁冲突

如果没有加意向锁,那么在加表锁时,就需要遍历表中所有记录,去查看是否有记录已经存在独占锁,这样遍历效率比较慢,所以意向锁的目的就是为了快速判断表里是否有记录被加锁了


7.数据库中char和varchar的区别

char的长度是不可变的,而varchar的长度是可变的
取数据的时候,char类型的要用trim()去掉多余的空格,而varchar是不需要的。
插入数据超过规定长度,都会返回错误。
char的存取速度还是要比varchar要快得多,因为其长度固定,方便程序的存储与查找;
但是char也为此付出的是空间的代价,因为其长度固定,所以难免会有多余的空格占位符
占据空间,可谓是以空间换取时间效率,而varchar是以空间效率为首位的。

8.一条mysql更新语句是如何执行的

  1. 客户端与MySQL的Server层建立连接后,建立连接后Server层会获得用户的权限,之后客户端将语句发给Server层 ;
  2. 解析器根据sql进行词法分析,语法分析,判断sql语句的语句是否正确,然后构建语法树。
  3. 预处理器检查表或字段是否存在;
  4. 优化器决定使用哪个索引,如果有多表连接,还会决定各个表的连接顺序,选择最优的执行计划
  5. 执行器在开始执行语句前,会对用户进行权限检验,判断用户是否有权限对该表进行操作,通过
    后,执行器调用存储引擎的接口,根据执行计划执行获得相应的数据,如果存储发现该数据本来就
    在buffer pool中,就直接返回给执行器更新,如果记录不在buffer pool中,就将数据页从磁盘读
    入到buffer pool中,之后返回记录给执行器。
  6. 执行器得到数据后,会判断更新前的数据跟更新后的数据是否一样,如果一样就不进行后续更新操
    作,如果不一样则就把更新前的数据和更新后的数据都当作参数传给InnoDB,让InnoDB执行更新
    记录的操作;
  7. 开启事务,InnoDB更新数据前,首先要记录这条数据的undo log,将undo log写入buffer pool的
    Undo页面中,(这条undo log写入操作,也要记录对应的redo log) 8. InnoDB开始更新数据,更新数据的同时记录redo log,将redo log写入到redo log buffer,此时redo log是prepare状态,然后告诉执行器,执行完成了,随时可以提交。
  8. 执行器收到通知后就生成这个操作的bin log,保存到binlog cache中。
  9. 执行器调用InnoDB的提交事务接口,InnoDB将redo log的状态改成commit。

9.redo log,undo log, bin log各自的作用

redo log

为了防止数据库发生故障导致数据丢失,当进行增删改操作的时候,InnoDB引擎会将这条记录具体是在哪个数据页、多少偏移量、做了哪些修改记录在redo log后,这样就能保证数据库在重启时能够恢复到故障前的最新状态。

undo log
  1. 实现事务回滚,保证了事务的原子性,事务处理的过程中,如果出现错误或者我们主动执行了
    ROLLBACK语句,MySQL就可以利用undo log中的历史数据将数据恢复到事务开始之前的状态。
  2. 跟Read View配合实现MVCC(多版本并发控制),MVCC就是通过Read View和undo log的版本链来来实现的,当MySQL执行快照读的时候,可以根据Read View的信息,顺着undo log的版本链找到可见的数据。
bin log

binlog文件是记录了所有数据库表结构和表数据修改的日志,它主要是用于复制,在主从复制中,从库
利用主库上的bin log进行重播,实现主从同步,它还相当于数据库的备份,如果我们不小心将数据库的数据删除了,可以用binlog文件恢复数据.


10.乐观锁与悲观锁

悲观锁

悲观锁就是每次都假设是最坏的情况,每次查询数据时都认为会有其他事务来修改数据,所以每次查询记录时都会利用锁机制给数据加上排他锁,这样其他事务想要操作这条数据就会阻塞等待当前事务的提交。

乐观锁

乐观锁就是每次都假设不会发生并发冲突,不会给数据加锁,只在更新的时候会判断在此期间有没有其他事务更新了这条数据,可以使用版本号机制或者CAS机制实现,乐观锁适用于读多写少的情况。

11.MVCC

MVCC是多版本并发控制,通过数据行的版本链来实现数据库的并发控制,主要是为了解决读写冲突,而且这个读是快照读(注意跟当前读区分开),MVCC是通过undo log和Read View实现的。

首先Read View会有四个字段,分别是
creator_trx_id:它表示的是创建这个Read View的事务ID
trx_ids:它表示的是生成Read View时当前数据库活跃的事务(就是那些未提交的事务)列表
up_limit_id,活跃的事务中最小的事务ID
low_limit_id,当前数据库最大的事务ID+1

然后每个聚簇索引记录都有两个隐藏字段,一个是trx_id,就是记录了当前操作这条记录的事务ID,还有一个roll_pointer,一个指向了它的旧版本的指针,所以每条记录都会有一条版本链,这些旧版本都写在undo log里面。

然后就会有四种情况

  • 如果查询的数据当前版本的trx_id等于当前自身事务的trx_id,就说明这条数据被自身事务更新过,所以一定可见;

  • 那如果trx_id小于Read View的up_limit_id,表示这个版本的记录是在创建Read View前就已经提交的事务生成的,所以这个版本的记录对当前事务可见;

  • 如果trx_id大于等于Read View的low_limit_id,表明这个版本的记录是在创建Read View后生成的,所以这个版本的记录对当前事务不可见;

  • 如果trx_id在up_limit_id和low_limit_id之间,就需要判断trx_id是否在trx_ids中

    • 如果记录的trx_id在列表中,表明生成该版本记录的事务依旧活跃着,也就是还没提交,所以该版本的记录对当前事务不可见。

    • 如果记录的trx_id不在列表中,表明生成该版本记录的事务已经被提交了,所以该版本的记录对当前事务可见。

如果隔离级别是读提交的话,每次执行快照读前都会重新生成一个Read View。
如果隔离级别是可重复读的话,在第一次执行快照读前会生成一个Read View,之后整个事务都在用这个Read View。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Q_Outsider

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值