用于管理对共享资源的并发访问,从而保证数据的完整性和一致性
一个事务想对某条记录做改动时,首先会看看内存中有没有与这条记录关联的锁结构,当没有的时候就会在内存中生成一个锁结构与之关联。 比方说事务T1要对这条记录做改动,就需要生成一个锁结构与之关联:
trx信息:代表这个锁结构由哪个事务生成的is_waiting:代表当前事务是否等待几种加锁说法
不加锁:即不生成锁结构加锁成功:生成锁结构,is_waiting是false加锁失败: 生成锁结构,is_waiting是trueMySQL全局锁、表锁、行锁
只有同时是共享锁(S锁)的时候兼容,其他组合均互斥,即排他锁(X锁)与 任何锁都不兼容。
InnoDB 支持多粒度的锁,这种锁允许事务在行级锁和表级锁同时存在。
为支持在不同粒度上进行加锁操作,InnoDB存储引擎支持一种额外的锁方式,称之为意向锁(Intention Lock), 为表级别的锁。
意向共享锁(IS Lock): 当事务需要在某条记录上S锁的时候,需要在表级别加一个IS锁。意向排他锁(IX Lock): 当事务需要在某条记录上X锁的时候,需要在表级别加一个IX锁。IS、IX锁是表级锁,它们的提出仅仅为了在之后加表级别的S锁和X锁时可以快速判断表中的记录是否被上锁,以避免用遍历的方式来查看表中有没有上锁的记录,也就是说其实IS锁和IX锁是兼容的,IX锁和IX锁是兼容的,本质上只是一种标记。
MySQL事务隔离级别详解及MVCC实现原理
通过加锁方式,实现操作的排队执行。由于对某行记录加读写锁之后,不能同时修改,所以解决了脏读问题、不可重复读问题,幻读问题,可以通过加间隙锁的方式来解决。
事务利用MVCC进行的读取操作称之为一致性读,或者一致性无锁读,有的地方也称之为快照读。
所有普通的SELECT语句(plain SELECT)在READ COMMITTED、REPEATABLE READ隔离级别下都算是一致性读,是不会对表中任何记录加锁的。
如果读取的行正在执行DELETE或UPDATE操作,这时读取操作不会因此去等待行上锁的释放
InnoDB存储引擎的SELECT操作使用一致性非锁定读,但在某些情况下,用户需要显式地对数据库读取操作进行加锁以保证数据逻辑的一致性。
锁定读的语句:
对读取记录加一个S锁,其他事务只能加S锁,不能加X锁
SELECT ... LOCK IN SHARE MODE;对读取记录加一个X锁,其他事务不能对已锁定的行加任何锁
SELECT ... FOR UPDATE;常见写操作
DELETE:定位待删除记录在B+树中位置的过程看成是一个获取X锁的锁定读。UPDATE:键值、空间不变,X锁,键值不变,空间变,首先定位为X锁,插入用隐式锁,键值变,相当于删除,后插入INSERT:新插入一条记录的操作并不加锁,通过隐式锁来保护这条新插入的记录在本事务提交前不被别的事务访问例如一个索引有10,11,13和20这四个值,那么该索引可能被Next-Key Locking的区间为:(负无穷,10],(10,11] ,(11,13],(13,20],(20,正无穷)
当查询的索引是唯一属性的时候,InnoDB存储引擎会对Next-Key Lock优化,将其降级为Record Lock。
MySQL InnoDB的可重复读并不保证避免幻读,需要应用使用加锁读来保证,在可重复度隔离级别下,且禁用innodb_locks_unsafe_for_binlog的情况下,InnoDB存储引擎采用Next-Key Locking机制来避免幻读问题。
因为不同锁之间的兼容性关系,在有些时刻一个事务中的锁需要等待另一个事务中的锁释放它所占用的资源,这就是阻塞。阻塞并不是一件坏事,其是为了确保事务可以并发且正常地运行。
两个或两个以上的事务在执行过程中,因争夺资源而造成的一种互相等待的现象。
解决死锁问题
注意:
read uncommitted 读不加锁,写加排他锁,并到事务结束之后释放。