MySQL–innodb存储学习之锁

锁概述

开发多用户、数据库驱动的应用时,最大的一个难点是:一方面要最大程度地利用数据库的并发访问,另外一方面还要确保每个用户能以一致的方式读取和修改数据。为此就有了锁(locking)的机制,同时这也是数据库系统区别于文件系统的一个关键特性。
InnoDB存储引擎会在行级别上对表数据上锁,这固然不错。不过InnoDB存储引擎也会在数据库内部其他多个地方使用锁。从而允许对多种不同资源提供并发访问。例如,操作缓冲池中的LRU列表,删除、添加、移动LRU列表中的元素,为了保证一致性 必须有锁的介入(线程锁 丰键id自增,#有的共享资源、上锁、线程锁)。
   数据库系统使用锁是为了支持对共享资源进行并发访问,提供数据的完整性和一致性。对于MyISAM引擎,其锁是表锁设计(innodb存储也有表锁,但是与行锁不冲突)。并发情况下的读没有问题,但是并发插入时的性能就要差一些了,若插入是在“底部”,MyISAM存储引还是可以有一定的并发写入操作。
  在数据库中,lock与latch都可以被称为“锁”。但是两者有着截然不同的含义,本章主要关注的是lock。latch一般称为门锁(轻量级的锁),因为其要求锁定的时间必须非常短。若持续的时间长,则应用的性能会非常差。在InnoDB存储引擎中,latch又可以分为mutex(互斥量)和rwlock(读写锁)。其目的是用来保证并发线程操作临界资源的正确性,并且通常没有死锁检测的机制。
  lock的对象是事务,用来锁定的是数据库中的对象,如表、页、行。并且一般lock的对象仅在事务commit或rollback后进行释放(不同事务隔离级别释放的时间可能不同)。此外,lock,正如在大多数数据库中一样,是有死锁机制的。

lock与latch区别

InnoDB存储引擎中的锁

InnoDB存储引擎实现了如下两种标准的行级锁:
❑共享锁(S Lock),允许事务读一行数据。
❑排他锁(X Lock),允许事务删除或更新一行数据。

X锁与任何的锁都不兼容,而S锁仅和S锁兼容。需要特别注意的是,S和X锁都是行锁,兼容是指对同一记录(row)锁的兼容性情况。
s锁与x锁
InnoDB存储引擎支持意向锁设计比较简练,其意向锁即为表级别的锁。设计目的主要是为了在一个事务中揭示下一行将被请求的锁类型。其支持两种意向锁:
1)意向共享锁(IS Lock),事务想要获得一张表中某几行的共享锁
2)意向排他锁(IX Lock),事务想要获得一张表中某几行的排他锁

IS IS, IS IX, IX IS , IX IX 不会有不兼容的情况。

由于InnoDB存储引擎支持的是行级别的锁,因此意向锁其实不会阻塞除全表扫以外的任何请求。

意向锁存在的意义?

(我有一个需求,我现在就需要查询出所有的表里的数据。select * from table;
这个语句是不是 innodb引擎进行执行啊? 是不是需要确保所有的行都没有被x加锁啊?
如何保证所有的行没有加x锁啊? x 行锁 可以吗? 可以啊:一条条查不就行了。这样有点慢。
Innodb存储引擎想了招儿,IX 锁不就行了,直接检查是否有IX 锁就行了,如果有就阻塞。)

从InnoDB1.0开始,在INFORMATION_SCHEMA架构下添加了表INNODB_TRX、INNODB_LOCKS、INNODB_LOCK_WAITS。通过这三张表,用户可以更简单地监控当前事务并分析可能存在的锁问题。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

一致性的非锁定读(consistent nonlocking read)

是指InnoDB存储引擎通过行多版本控制(multi versioning)的方式来读取当前执行时间数据库中行的数据。如果读取的行正在执行DELETE或UPDATE操作,这时读取操作不会因此去等待行上锁的释放。相反地,InnoDB存储引擎会去读取行的一个快照数据。之所以称其为非锁定读,因为不需要等待访问的行上X锁的释放。快照数据是指该行的之前版本的数据,该实现是通过undo段来完成。而undo用来在事务中回滚数据,因此快照数据本身是没有额外的开销。此外,读取快照数据是不需要上锁的,因为没有事务需要对历史的数据进行修改操作。

一个行记录可能有不止一个快照数据,一般称这种技术为行多版本技术。由此带来的并发控制,称之为多版本并发控制(Multi Version Concurrency Control,MVCC)。

在事务隔离级别READ COMMITTED和REPEATABLE READ(InnoDB存储引擎的默认事务隔离级别)下,InnoDB存储引擎使用非锁定的一致性读。然而,对于快照数据的定义却不相同。在READ COMMITTED事务隔离级别下,对于快照数据,非一致性读总是读取被锁定行的最新一份快照数据。而在REPEATABLE READ事务隔离级别下,对于快照数据,非一致性读总是读取事务开始时的行数据版本。

在默认配置下,即事务的隔离级别为REPEATABLE READ模式下,InnoDB存储引擎的SELECT操作使用一致性非锁定读。但是在某些情况下,用户需要显式地对数据库读取操作进行加锁以保证数据逻辑的一致性。而这要求数据库支持加锁语句,即使是对于SELECT的只读操作。InnoDB存储引擎对于SELECT语句支持两种一致性的锁定读(locking read)操作:
❑SELECT…FOR UPDATE
❑SELECT…LOCK IN SHARE MODE
SELECT…FOR UPDATE对读取的行记录加一个X锁,其他事务不能对已锁定的行加上任何锁。SELECT…LOCK IN SHARE MODE对读取的行记录加一个S锁,其他事务可以向被锁定的行加S锁,但是如果加X锁,则会被阻塞。

自增长与锁

在这里插入图片描述
虽然AUTO-INC Locking从一定程度上提高了并发插入的效率,但还是存在一些性能上的问题。首先,对于有自增长值的列的并发插入性能较差,事务必须等待前一个插入的完成(虽然不用等待事务的完成)。其次,对于INSERT…SELECT的大数据量的插入会影响插入的性能,因为另一个事务中的插入会被阻塞。

从MySQL 5.1.22版本开始,InnoDB存储引擎中提供了一种轻量级互斥量的自增长实现机制,这种机制大大提高了自增长值插入的性能。并且从该版本开始,InnoDB存储引擎提供了一个参数innodb_autoinc_lock_mode来控制自增长的模式,该参数的默认值为1。
在这里插入图片描述
在这里插入图片描述

锁算法

InnoDB存储引擎有3种行锁的算法,其分别是:
❑Record Lock:单个行记录上的锁
❑Gap Lock:间隙锁,锁定一个范围,但不包含记录本身
❑Next-Key Lock∶Gap Lock+Record Lock,锁定一个范围,并且锁定记录本身

Record Lock总是会去锁住索引记录,如果InnoDB存储引擎表在建立的时候没有设置任何一个索引,那么这时InnoDB存储引擎会使用隐式的主键来进行锁定。

Next-Key Lock是结合了Gap Lock和Record Lock的一种锁定算法,在Next-Key Lock算法下,InnoDB对于行的查询都是采用这种锁定算法。例如一个索引有10,11,13和20这四个值,那么该索引可能被Next-Key Locking的区间为:
(-∞,10]
(10,11]
(11,13]
(13,20]
(20,+∞)
采用Next-Key Lock的锁定技术称为Next-Key Locking。其设计的目的是为了支持一些不需要使用幻读和不可重复读的场景。当查询的索引含有唯一属性时,InnoDB存储引擎会对Next-Key Lock进行优化,将其降级为Record Lock,即仅锁住索引本身,而不是范围。
在这里插入图片描述

死锁

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值