InnoDB 锁

锁是InnoDB保障事务隔离性的重要手段,各个存储引擎以及DB的锁的实现是不同的。

  • MySql中,MyISAM采用表锁,InnoDB基于行锁。
  • Sql Server 2005支持乐观锁和悲观锁并发;
  • InnoDB提供一致性的非锁定读和行级锁,类似Oracle;

Lock和Latch

latch为轻量级锁,称为闩锁,latch类似Java的synchronize,但是Lock更宏观,latch可以认为是程序性控制,控制程序逻辑,但是lock是对数据的保护。

Lock Latch
对象 事务
保护 数据库内容
持续时间 整个事务过程
模式 行锁、表锁、意向锁
死锁处理 通过wait-for graph、time out等进制进行处理
存在位置 Lock Manager的哈希表中

InnoDB的锁

InnoDB实现了两个标准锁,这两个锁是基于行设计的。

  • 共享锁:S Lock,允许对row数据共享的read;
  • 排他锁:X Lock,允许对row数据update、delete,但是是独占的;

意向锁:InnoDB实现的一种特殊的表锁,揭示接下来将要获取的锁的类型,意向锁分为以下两类:

  • IX:意向排他锁;
  • IS:意向共享锁;
  • 意向锁不会阻塞除全表扫描以外的任何请求;

锁相关Sql

#查看引擎状态查看锁
show engine innodb status;

#查看处理过程
show full processlist;

# 查询schema数据库
select * from information_schema.INNODB_TRX \G

一致性非锁定读

InnoDB的读策略是:在读取数据的时候不加锁,也不需要等待X锁的释放即可读取数据,这时读取的是数据的快照版本。每个数据,由于并发的事务不同,可能存在多个快照数据,这就是多版本快照。

InnoDB使用多版本快照并发控制技术 - MVVC技术控制读取数据的快照版本。
MVVC技术也是InnoDB实现非锁定读的关键技术。

事务不同隔离级别的快照版本确定方式不一样。InnoDB尽在下面两个级别下使用非锁定读技术,其数据快照版本确定方式如下:

  • read commited:读已提交级别,读取最新的一个快照版本;
  • repeatable read:可重复读级别,读取事务开始时的快照版本;

MVVC技术中确定数据快照版本的时候通过事务号,所以事务号是以关键!

显示加锁Sql

InnoDB支持显示加锁语句,通过在Select的时候加入关键语句可以加X和S锁。这些语句是InnoDB特有的,不是Sql标准。

#Select语句的支持:
# 加X锁;
select ... for update;

# 加S锁;
select ... lock in share mode;

自增长字段和锁

InnoDB实现自增长算法有两种模式,一种轻量级互斥量,一种是表锁,MyISAM则采用全表锁。

InnoDB中自增长的列必须是索引的第一列,也必须是索引。

外键和锁

InnoDB自动为外键添加索引,这可以避免表锁。如果有外键,InnoDB在Insert的时候会去check父表数据,这是会有一个父表的隐式的select操作,这种select不采用一致性非锁定读,而且采用Select id from parent_table in lock share model,即主动加S锁。所以外键固然可以保证数据完整性,但是同样有性能隐患。

锁算法

InnoDB有3种行锁算法:

  • Record Lock:单个行上锁;
  • Grap Lock:间隙锁,锁定一个范围,但是不锁定本身,锁定范围为开区间;
  • Next-Key Lock:锁定范围包括本身,锁定范围为闭区间;

这三种锁在不同的事务隔离级别下别使用。如InnoDB通过Nex-Key Lock算法锁定一个范围数据,这样可以避免幻读。

如果字段是唯一索引,则Next-Key Lock有可能降级为Record Lock;

锁带来的问题

锁可以很好的支持数据库事务,保证事务的隔离性,但是锁的不正确使用也会带来一些问题。在事务的隔离级别中,各个隔离级别都会有一定的问题,这就是锁带来的。

  • 在read-ncommitted级别下,因为没有使用锁,所以会发生脏读问题;
  • 在read committed级别下,因为使用Record Lock策略,但是没有对范围加锁,所以会有幻读和不可重复读问题;
  • 在repeatable read级别下,因为使用的是Next-Key Lock策略,所以可以消除脏读和幻读,但是是否有效率问题呢?

Next-Key Lock :InnoDB解决幻读策略

幻读简单描述是一个事务两次读取时读取到了不同的行数,幻读和不可重复读的区别在于,不可重复读是两次读取同一个数据行,数据行内容发生了update,但是幻读多发生在insert和delete中。

InnoDB使用Next-Key Lock算法作为Repeatable Read的加锁策略,这种方式锁定一个范围,保证事务隔离性。Read Commited 使用Record Lock作为加锁策略,无法保证事务隔离性。

你可能感兴趣的:(mysql,总结)