面试准备 --- 数据库事务

面试准备,仅为一家之言,无法保证理解正确性,慎,欢迎纠正

数据库事务

ACID

  • A : Atomic:原子性:指数据库事务要么完成,要么不做.是一个不可分割的原子操作;
  • C:consistency: 一致性:指事务完成要保证业务逻辑数据一致;即业务是A账户向B账户转账,无论怎么转,事务完成后必须保证A账户和B账户的总额不变;
  • I:Isolation: 隔离性: 指不同事务有自己的执行空间,各自的操作不会影响到其他事务的执行;这里可以通过设置不同的隔离级别来控制事务的隔离强度,隔离级别越高,数据一致性越好,并发性能越低;
  • D: Durability:持久性: 一旦事务成功提交,对数据的操作必须写进数据库中,即使是事务刚提交,数据库就崩溃,也要保证下一次重启时,之前的数据操作可以写到数据库中;

InnoDB对ACID的实现

事务的ACID是通过InnoDB日志和锁来保证。事务的隔离性是通过数据库锁的机制实现的,持久性通过redo log(重做日志)来实现,原子性和一致性通过Undo log来实现。UndoLog的原理很简单,为了满足事务的原子性,在操作任何数据之前,首先将数据备份到一个地方(这个存储数据备份的地方称为UndoLog)。然后进行数据的修改。如果出现了错误或者用户执行了ROLLBACK语句,系统可以利用Undo Log中的备份将数据恢复到事务开始之前的状态。
和Undo Log相反,RedoLog记录的是新数据的备份。在事务提交前,只要将RedoLog持久化即可,不需要将数据持久化。当系统崩溃时,虽然数据没有持久化,但是RedoLog已经持久化。系统可以根据RedoLog的内容,将所有数据恢复到最新的状态。
对具体实现过程有兴趣的同学可以去自行搜索扩展。

链接:https://juejin.im/post/5b5a0bf9f265da0f6523913b

数据库并发问题

  • 脏读: A事务读取了B事务尚未提交的更改数据,并使用这个数据进行后续操作,但是B事务回滚,撤销了事务,B事务更改的数据就会被恢复为原来的值,但是A事务使用了被修改的值后又进行了一系列的操作;
  • 不可重复读: 指A事务分别在B事务开始和结束后读取了被B修改的值,造成A事务的操作数据不一致;
  • 幻读: 类似不可重复读,指A事务是在B事务新增数据操作前后读取到了包括新增数据的总数据,而造成数据不一致的问题;主要是前一次读取时还满足要求,但在执行时又不满足了;
  • 不可重复读和幻读的区别在于不可重复读读的是修改数据,而幻读读的是新增数据,数据库处理二者的操作也是不同的,对于不可重复读,只需要对操作的数据添加行锁,阻止操作中数据发生变换;而防止读到新增数据,就需要添加表级别的锁–整张别锁定,防止新增数据;也许正是因为防止操作的不同,才对这两种问题做区分;
  • 第一类丢失更新: 我觉得类似脏读,指A事务先读到一个值a,在后续操作前,B事务将该值修改为b,然后提交事务,然后A在原来读取到的值a的基础上继续执行,并做了修改为c,但是因为一些问题发生回滚,值被回滚到a,这时,B事务的操作就被丢失了,造成数据不一致;
  • 第二类丢失更新: 类似第一类丢失更新,指A事务先读到一个值a,然后B事务开始并将a修改为b,提交事务,但是A事务继续执行,经a修改为c,这时丢失了B事务的更新;

事务隔离级别

隔离级别 脏读 不可重复读 幻读 第一类丢失更新 第二类丢失更新
READ UNCOMMITED 允许 允许 允许 不允许 允许
READ COMMITED 不允许 允许 允许 不允许 允许
REPEATABLE READ 不允许 不允许 允许 不允许 不允许
SERIALIZABLE 不允许 不允许 不允许 不允许 不允许
  • 未提交读: 一个事务可以读到另一个未提交的事务修改的值;
  • 提交读: 本事务读到的数据是最新的,也就是说一个事务内相同的query操作可以得到不同的结果(中间有其他事务提交)
  • 可重复读: 本事务的相同的多次query操作得到的结果是一样的
  • 串行读: 事务间有类似读写锁的锁机制,并发读允许,并发写不允许
  • READ UNCOMMITED拥有最高的并发度和吞吐量,而SERIALIZABLE并发量最低;
  • Mysql 默认采用的 REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别.

数据库锁机制

按所对象分可以分为表锁定和行锁定,前者对整张表锁定,后者对特定行锁定,从并发事务关系来看可以分为共享锁和独占锁;共享锁允许其他共享锁进入,排斥独占锁,而独占锁即防止共享锁也防止独占锁;

  • 行共享锁定:通过sql语句中select ... for update或者lock table in row share mode(oracle)获得共享锁定,

  • 行独占锁定:通过sql语句insert|update|delete 或者 lock table in row exclusive mode这些语句都是;

  • 表 共享锁定: 通过lock table in share mode,表共享可以防止行独占锁定和表独占锁定,允许表共享和行共享

  • 表共享行锁定 通过lock table in share row exclusive mode 显式获得,这种锁定可以防止其他回话获取一个表共享,行独占,或者表独占;只允许行共享

  • 表独占: 通过lock table in exclusive mode语句显示获得,什么都不允许

  • MyISAM使用的是表级锁, InnoDB使用的是行级锁

InnoDB行级锁算法

  • Record Lock: 单行记录上的锁
  • Gap lock: 间隙锁,锁定一段距离,不包括记录本身
  • Next-key lock: record+gap,锁定一段距离,包括记录本身
  • 三种锁的具体讲解,可以看这篇博客:InnoDB锁机制
  • 使用next-key lock主要是为了解决幻读的问题,首先看上面对幻读的理解,是指对一段范围内的多次查询查询出不同的结果,例如select * from table where age < 10 ;我寻找年龄小于10的记录,如果在两次查询中,有事务新增了或者删除了小于10的某条记录,这时获得的结果就不同了.如果只使用record lock,锁住一行记录,是无法解决这个问题的,只有锁住一个范围,才能解决,至于具体的如何规划范围和如何处理等待锁的事务,看上一条的链接博客;

猜你喜欢

转载自blog.csdn.net/qq_36865108/article/details/86758807
今日推荐