一名合格的后端开发,到底需要多了解mysql - 6&7

6 - 锁

lock 和 latch

latch:内存中的轻量级互斥量或读写锁,其目的是为了保证并发线程操作临界资源的正确性。无死锁检测和处理机制。
lock:锁定数据库中的对象,比如表,页,行等,其目的是为了保证并发事务操作表对象的正确性。可通过 等待有向图 和 超时机制进行死锁检测和处理。

以下讨论的内容都是和lock相关的

Innodb中锁的类型

行级锁:

  • 共享锁(读锁):可以和其他共享锁并行
  • 排它锁(写锁):不能和任何其他锁并行

表级锁:

  • 共享锁
  • 排他锁
  • 意向共享锁
  • 意向排他锁
    意向锁之间不互斥,意向锁和任何行级锁之间不互斥
    意向锁只和表级锁互斥,其存在目的是为了快速判断该表是否有行级读锁或写锁,便于快速阻塞表锁获取。

一致性非锁定读 by MVCC

MVCC:每个被更新行记录在事务提交之前,会在undo中存储该行之前版本的数据快照。每行记录可能会有多条undo保存多个版本的快照,因此称为多版本并发控制。

不同隔离级别对使用的快照定义不同
Read Committed:总是读取最新一条快照的数据
Read Repeatable:总是读取事务开始时的快照数据

一致性锁定读:

对读取的记录加X锁:select ... for update
对读取的记录加S锁:select ... lock in share mode

行级锁的算法

  • Record Lock:行锁,锁定单条记录
  • Gap Lock:间隙锁,锁定一个范围,但不包括记录本身
  • Next-Key Lock:行锁+间隙锁,锁定一个范围,且包括记录本身
    Next-Key Lock的存在目的是为了解决Read Repeatable隔离级别下的幻读问题。当按索引范围查询数据时,其锁定范围上界到上一个索引以及下界到下一个索引,使这个范围内无法添加或删除行记录,保证多次读取的行数据一致。

锁问题

  • 脏读:
    读到其他事务还未提交的数据。Fix: I >= Read Committed
  • 不可重复读/幻读
    事务内多次读取同一数据集合,由于中途有其他事务提交,导致两次读取读到的数据可能是不一样的。 有两种不一样的可能:数据内容不一致 OR 数据行数不一致。I >= Read Repeatable
  • 丢失更新
    业务逻辑导致的数据更新丢失,可以考虑将数据获取-更新逻辑串行化,或采用乐观锁机制来保证数据一致性。

死锁检测

对事务-锁进行建模,将其依赖关系构建成一个有向依赖图,当有向图中出现环的时候,即代表出现了死锁。

7 - 事务

事务的基础 ACID

  • A 原子性:一个事务要么全部执行,要么全部不执行
  • C 一致性:事务执行总是从一个满足一致性的状态到另一个一致性状态
  • I 隔离性:事务和事务之间在执行中互相隔离
  • D 持久性:事务执行一旦成功,其结果就是永久性的

事务的实现

  • redo log: 持久性
  • undo log: 原子性
  • 锁: 隔离性,一致性

undo log

不同于redo log的物理修改,undo log存储的是回滚的逻辑修改。

undo log分为两种类型
  • insert undolog:对应insert操作,新增的数据只对事务本身可见,因此提交后可直接删除。
  • update undolog:对应update,delete操作。该类undolog需要提供MVCC机制,因此提交后被放入待purge链表,在不被任何事务引用后被purge删除。
undo 和 MVCC

每行数据里记录了最后一条修改该行的trx_id,同时记录了最后一次修改的roll_back_ptr。和行数据类似,update undolog里也记录了trx_id和roll_back_ptr。事务执行时,可以通过比对trx_id(trx_id单调递增)沿着roll_back_ptr一直找到事务开始前的最新一条记录,即RR级别下的行快照。

分布式事务 & 二阶段提交

分布式事务使用两段式提交,第一阶段,所有参与事务的节点都进行准备,告知事务管理器它们准备好了。第二阶段,由事务管理器告知节点执行rollback还是commit。

binlog和redo log间的二阶段提交

binlog和redo log的写入需要是原子的,以防止在复制从节点时出现数据异常问题。mysql通过在binlog和innodb间使用二阶段提交来解决该问题。具体执行顺序如下:

  1. innodb prepare 事务,将事务的xid写入
  2. mysql 写入 binlog
  3. 事务提交,innodb 写入 redolog

宕机后,检查xid事务是否提交,如未提交则主动进行一次提交,如果binlog没写入,那么额外写入一次binlog。因此在2,3任一环节宕机,都可以保证数据一致性。

你可能感兴趣的:(后端mysqlinnodb面试)