MySQL进阶-锁与事务

什么是锁

  • 锁机制用于管理对共享资源的并发访问

lock与latch

  • latch一般称为闩锁(轻量级锁),因为其要求锁定的时间必须非常短。在InnoDB中,latch又可以分为mutex(互斥量)和rwlock(读写锁)。其目的是用来保证并发线程操作临界资源的正确性,并且通常没有死锁检测的机制
  • lock的对象是事务,用来锁定的是数据库中的对象,如表、页、行。一般lock的对象仅在事务commit或rollback后进行释放。
    在这里插入图片描述

InnoDB存储引擎中的锁

锁的类型

  • InnoDB存储引擎实现了如下两个标准的行级锁:
    • 共享锁(S Lock),允许事务读一行数据
    • 排他锁(X Lock),允许事务删除或更新一行数据
    • X锁与任何锁都不兼容,S锁仅与S锁兼容
  • InnoDB存储引擎支持多粒度(granular) 锁定,为了支持在不同粒度上进行加锁操作,InnoDB引擎支持意向锁(Intention Lock)
    • 如果对最细粒度的对象进行上锁,首先要对粗粒度的对象进行上锁
    • 在InnoDB存储引擎中,其意向表即为表级别的锁
      • 意向共享锁(IS Lock),事务想要获得一张表中某几行的共享锁
      • 意向排他锁(IX Lock),事务想要获得一张表中某几行的排他锁
      • 意向锁不会阻塞全表扫以外的任何请求

一致性非锁定读

  • 一致性的非锁定读(consistent nonlocking read)指的是InnoDB存储引擎通过多版本控制(multi versioning)的方式去读取当前执行时间数据库中行的数据。如果读取的行正在执行DELETE或UPDATE操作,这时读取操作不会因此去等待行上锁的释放。InnoDB存储引擎会去读取行的一个快照数据。
  • 快照数据是指该行的之前版本的数据,通过undo段实现。
  • 一个行记录可能有不止一个快照数据,一般称这种技术为行多版本技术,由此带来的并发控制,称之为多并发控制(Multi Version Concurrency Control,MVCC)
  • 在事务隔离级别READ COMMITED和REPEATABLE READ下,InnoDB存储引擎使用非锁定的一致性读。对于快照数据而言,在READ COMMITED事务隔离级别下,读取的是被锁定行最新一份快照数据;在REPEATABLE READ事务隔离级别下,读取的是事务开始时的行数据版本。

一致性锁定读

  • 当用户显式地对数据库读取操作进行加锁以保证数据逻辑的一致性。

锁的算法

行锁的3种算法

  • Record Lock:当个行记录上的锁
  • Gap Lock:间隙锁,锁定一个范围,但不包含记录本身
  • Next-Key Lock:Gap Lock+Record Lock,锁定一个范围,并且锁定记录本身

解决Phantom Problem

  • InnoDB存储引擎采用Next-Key Locking机制来避免Phantom Problem。
  • Phantom Problem是指在同一事务下,连续执行两次同样的SQL语句可能导致不同的结果,第二次的SQL语句可能会返回之前不存在的行

锁问题

脏读

  • 脏数据是指未提交的数据,如果读到了脏数据,即一个事务可以读到另外一个事务中未提交的数据。
  • 脏读发生的条件是事务隔离级别为READ UNCOMMITED

不可重复读

  • 不可重复读是指一个事务内多次读取同一数据集合,在这个事务还没有结束的时候,另外一个事务也访问该同一数据集合,并做了DML操作(比如修改)。导致第一个事务两次读到的数据可能是不一样的。
  • 不可重复读的条件是事务隔离级别是READ COMMITED

丢失更新

  • 丢失更新是一个事务的更新操作会被另一个事务的更新操作锁覆盖,从而导致数据的不一致
  • 丢失更新的条件是REAPTABLE READ。为避免这种情况,需要将事务的操作序列化。

阻塞

  • 由于不同锁之间的兼容性关系,在有些时刻一个事务中的锁需要等待另一个事务中的锁释放它锁占用的资源。
  • 为了确保事务可以并发且正常地运行

死锁

死锁的概念

  • 死锁是指两个或两个以上的事务在执行过程中,因争夺所资源而造成的一种互相等待的现象
  • 解决方式:wait-for graph死锁检测机制,在每个事物请求锁并发生等待时都会判断是否存在回路,若存在则有死锁,通常InnoDB存储引擎选择回滚undo量最小的事务

死锁概率

  • 纯数学推导请看书籍
  • 事务发生的概率与以下几点因素有关
    • 系统中事务的数量,数量越多发生死锁的概率越大
    • 每个事务操作的数量越多,发生死锁的概率越大
    • 操作数据的集合越小,发生死锁的概率越大

锁升级

  • 锁升级(Lock Escalation)是指将当前锁的粒度降低。比如,数据库可以把一个表的1000个行锁升级为一个页锁,或者将页锁升级为表锁。

事务

  • InnoDB存储引擎中的事务完全符合ACID的特性
    • 原子性(atomicity)
    • 一致性(consistency)
    • 隔离性(isolation)
    • 持久性(durability)

认识事务

概述

  • 原子性(atomicity),指整个数据库事务是不可分割的工作单位。只有使事务中所有的数据库操作都执行成功,才算整个事务成功。事务中任何一个SQL语句执行失败,已经执行成功的SQL语句也必须撤销,数据库状态应该退回到执行事务前的状态
  • 一致性(consistency),指事务将数据库从一种状态转变为下一种一致的状态。在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
  • 隔离性(isolation) ,要求每个读写事务的对象对其他事务的操作对象能够相互分离,即该事务提交前对其他事务都不可见,通常这使用锁来实现。
  • 持久性(durability),事务一旦提交,其结果就是永久性的。就算发生宕机等故障,数据库也能将数据恢复。

事务的实现

  • 原子性、一致性、持久性通过数据库的redo log和undo log来实现。redo log称为重做日志,用来保证事务的原子性和持久性。undo log用来保证事务的一致性

redo

  • 重做日志用来实现事务的持久性,其由两部分组成:一是内存中的重做日志缓冲(redo log buffer),其是易失的;二是重做日志文件(redo log file),其是持久的
  • 通过Force Log at Commit机制实现事务的持久性,即当事务提交(COMMIT)时,必须先将该事务的所有日志写入到重做日志文件进行持久化,待事务的COMMIT操作完成出才算完成。

undo

  • 当事务需要回滚操作的时候,就需要undo。如果用户执行的事务或语句由于某种原因失败了,又或者用户用一条ROLLBACK语句请求回滚,就可以利用这些undo信息将数据回滚到修改之前的样子。
  • undo存放在数据库内部的一个特殊字段(segement)中,这个字段称为undo段(undo segment)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值