MySQL每日面试题———事务

62 阅读6分钟

1.什么是数据库事务

是一组逻辑操作单元,使得数据从一种状态转变为另外一种状态,从而保证数据的一致性

2.事务的四大特性

ACID

  • atomicity(原子性)是指事务是一个不可分割的状态,要么都成功,要么都失败
  • consistency(一致性)保证事务从一个合法的状态转为另外一个合法的状态,满足预定的约束的状态就为合法的状态(例如A给B转20,B+20 A-20 但他们俩的总额就为20,20就为他们的合法状态)
  • isolation(隔离性)即两个(多个)事务之间互不干扰
  • duration(持久性)即事务提交以后就永久保存在磁盘中

3.事务的隔离级别有哪些?MySQL的默认隔离级别是什么

  • READ_UNCOMMIT(读未提交)只解决了脏写的问题,但是在修改数据的时候,即使数据未提交,也可以从其他事务中读取到该未提交的数据,该级别会导致脏读、不可重复读、幻读的情况发生
  • READ_COMMITED(读已提交)读已提交,是指事务与事务之间只能读取到已经提交的数据,解决了脏读的问题,但是幻读,不可重复读的问题还是会发生
  • REPETABLE_READ(可重复读)解决了事务A读取一行数据的时候,事务B对该行数据进行修改并且提交,导致了事务A中两次读取数据的不一致的问题
  • SERIALIZABLE(串行化)解决了当事务A获取数据,但事务B在对该表进行插入操作,事务A中两次获取的数据不一致的问题。
  • MySQL的默认隔离级别是RR(可重复读)

4.为何选择RC数据库隔离级别?

  • RC隔离级别,解决了脏读的问题,但是不可重复读和幻读都没有解决,在并发性能上,RC的性能肯定是比可重复读和串行化要快得多
  • 因为在RC隔离级别下,加锁的过程只需要对修改的记录进行加锁。如果在RR隔离级别,那么还会引入GapLocks和临键锁导致加锁的范围可能扩大,从而会影响并发,还容易造成死锁,因为间隙锁和间隙锁是不冲突的

5.并发情况下,数据库存在哪一些一致性问题

脏写、脏读、不可重复读、幻读

6.四大隔离级别,都会存在哪些并发问题

  • READ_UNCOMMIT(读未提交)解决了脏写的问题,但是没有解决,脏读,不可重复读,幻读的问题
  • READ_COMMITED(读已提交)解决了脏读和脏写的问题,但是没有解决,不可重复读,幻读的问题
  • REPETABLE_READ(可重复读)解决了脏读,脏写,不可重复读的问题,该算法包含了间隙锁,锁定一个范围,所以也解决了幻读的问题
  • SERIALIZABLE(串行化)解决了脏读,脏写,不可重复读,幻读。

7.MySQL隔离级别是如何实现的

MySQL的隔离级别是通过MVCC和锁机制来实现的

  • RU的隔离级别最低,没有加锁,存在脏读的问题
  • RC和RR的隔离级别可以通过MVCC来实现
  • 串行化是通过加锁的机制来实现的,读加共享锁,写加排他锁,如果有未提交的事务正在修改某些行,所有select 这些行的语句都会阻塞

8.什么是MVCC,底层原理

MVCC只对RR、RC这两种隔离级别有效,是以一种乐观锁的方式解决并发问题 MVCC的实现是由这三部分组成ReadView、undo版本链、隐藏字段

  • undo版本链 每个事务对当前数据行进行修改,那么undo版本链就会生成一条原来的数据行,由回滚指针来指向
  • 隐藏字段
    • roll_pointer 回滚指针,指向对于当前数据行最新的一次修改
    • trx_id 事务id
    • row_id 如果没有申明主键且没有唯一约束的字段,那么就会自动生成一个row_id来作为主键
  • ReadView
    • creator_trx_id:创建这个ReadView的ID
    • trx_ids:表示在生成ReadView时当前系统中活跃的读写事务的id列表(一个数组)
    • up_limit_id:活跃事务中最小的事务ID
    • low_limit_id:表示生成ReadView时系统应该分配给下一个事务的id值。是系统最大的事务id值,并不是正在活跃的事务ID
  • ReadView的规则
    • 如果被访问版本的trx_id属性值与creator_trx_id值相同,意味着当前事务在访问它自己修改过的记录,所以该版本能够被当前事务访问
    • 如果被访问的版本的trx_id属性值小于ReadView中的up_limit_id,那么说明当前事务生成的ReadView已经被提交,所以该版本可以被当前事务访问
    • 如果被访问的版本trx_id属性值大于ReadView中的low_limit_id,那么说明该版本的事务在当前事务生成ReadView后才开启,所以该版本不可以被当前事务访问
    • 如果被访问的版本的trx_id属性值在ReadView的up_limit_id和low_limit_id之间,那就需要判断trx_id是否在trx_ids中。如果在,则说明创建ReadView的时候该版本的事务还是活跃的,所以不能访问;如果不在,则说明创建ReadView的时候该事务已经提交了,所以可以访问
  • MVCC整体操作流程 当查询一条记录的时候,系统如何通过MVCC找到它:
  1. 首先获取事务自己的版本号
  2. 获取ReadView
  3. 查询到的数据,然后与ReadView中数据行的版本号进行比较
  4. 如果不符合ReadView规则,就需要从undo log中获取历史快照
  5. 最后返回符合规则的数据

10.如何实现可重复读

MySQL的InnoDB引擎,在默认的RR隔离级别下,实现了可重复读和解决了幻读的问题,它通过临键锁算法实现了行锁,并且不允许在读已经提交的数据,所以解决了不可重复读的问题。另外,还包含了间隙锁,所以也解决了幻读的问题

11.如何解决幻读问题

MySQL的InnoDB引擎,在默认的RR隔离级别下,实现了可重复读和解决了幻读的问题,它通过临键锁算法实现了行锁,并且不允许在读已经提交的数据,所以解决了不可重复读的问题。另外,还包含了间隙锁,所以也解决了幻读的问题

12.MySQL事务如何回滚

  • ROLLBACK:要使用这个语句的最简形式,只需发出ROLLBACK。同样地,也可以写为ROLLBACK WORK,但是二者几乎是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改。
  • ROLLBACK TO [SAVEPOINT] identifier :这个语句与SAVEPOINT命令一起使用。可以把事务回滚到标记点,而不回滚在此标记点之前的任何工作。