InnoDB锁的类型

  在一个高并发系统中,会出现多会话同时访问同一资源的情况,此时即产生了竞争。为了保证数据的一致性,必须要用锁机制来控制资源的并发访问。

InnoDB采用的行锁的设计(MyISAM只支持表锁),行锁带来更高的并发性,但管理复杂度也要比表锁更高。InnoDB共实现了2种标准的行级锁:

  • 共享锁(S Lock),允许持有锁的事务读取数据。
  • 排他锁(X Lock),允许持有锁的事务修改和删除数据。

其中仅S锁和S锁兼容,X锁与任何锁都不兼容。

意向锁(Intention locks):

InnoDB存储引擎支持多粒度的锁定,即允许行级锁和表级锁同时存在。意向锁共有两种

  • 意向共享锁(IS lock),表示事务想要获得表中某几行的共享锁。
  • 意向排他锁(IX lock),表示事务想要获得表中某几行的排他锁。

意向锁是一种表级锁,表示事务稍后希望在更细的粒度上(行级别)加锁。

  • select ... lock in share mode; 会对表施加IS锁。
  • select ... for update; 会对表施加IX锁。

表级别锁的兼容性如下图:

XIXSIS
XConflictConflictConflictConflict
IXConflictCompatibleConflictCompatible
SConflictConflictCompatibleCompatible
ISConflictCompatibleCompatibleCompatible

例如,如果请求在记录r上加X锁,则需要先在表级别上加意向排他锁(IX),如果此时表上存在其他锁,则意向锁需要等待表级别锁的释放,待表级意向锁(IX)获得成功后,才可以对行级别加X锁。

意向锁只会阻塞表级别的请求(如全表扫描、lock tables ... write;),除此之外不会阻塞任何操作。

记录锁(Record locks):

记录锁是对单一索引记录加的锁,即使表没有定义索引,InnoDB会为其建立一个隐藏的聚簇索引,并对此索引加记录锁。例如:select col from t where col=1 for update; 即对col为1的记录添加记录锁,阻止其他事务对此记录的操作。

间隙锁(Gap locks):

间隙锁是用来锁住一段索引区间的。例如:select col from t where col between 1 and 10 for update;会锁住1~10之间的间隙,而不管这段间隙内是否存在记录,因此间隙锁可能只锁住了一段空气。此时如果想插入为col为5的记录会被阻塞,即使5的记录不存在。间隙锁的唯一目的即是阻止其他的事务往间隙中插入记录,因此不同的事务可以对同样的间隙重复加锁,没用共享和排他类型之分。

间隙锁只在特性的隔离级别下使用,关闭间隙锁可以用2种方式:

  • 将事务的隔离级别设置为read committed
  • 将参数innodb_locks_unsafe_for_binlog(过时参数)设置为1

间隙锁是性能和并发之前的一个权衡,关闭间隙锁将破坏事务的隔离性。

临键锁(next-key locks):

Next-key lock 是记录锁和间隙锁的结合,next-key lock会对记录本身和记录之前间隙加锁。例如:假设表中存在索引记录1,10。则next-key lock可能锁住的范围是:

(-∞,1]

(1,10]

(10,+∞)

对于最后一个区间,next-key lock也会锁住最大记录之后的间隙。

Next-key lock只在MySQL的repeatable read隔离级别下使用,主要是用来解决幻读(phantom read)的问题。幻读即在同一个事务中,同样的查询读到了之前不存在的记录(由其他事务提交)。由于读到的是已提交的数据,因此很多DB厂商认为这不是问题,例如Oracle/SQLserver的默认隔离级别是read committed。是允许幻读和不可重复读存在的。而MySQL可以repeatable read隔离级别可以使用next-key lock实现事务的完全隔离。

当对唯一键值进行锁定时,next-key lock将会降级为record lock,即仅锁住唯一记录。而如果唯一键由多个列组成,而查询仅使用其中一列,则其实是range查询,InnoDB会依然使用next-key lock进行锁定。

插入意向锁(Insert intention locks):

插入意向锁是间隙锁的一种,其由inert语句在插入记录前获取,代表将在间隙中插入记录的意向。多个事务可以对同一个间隙重复加insert intention lock,只要插入的记录值不同,事务就不会冲突。例如表中已存在记录1和10,两个事务分别想插入5和6。两个事务都会对1和10记录之间的间隙(2,9)加insert intention lock,但由于插入的记录值不同,因此后续对要插入的记录获取X锁的时候并不会冲突。

自增锁(auto-inc locks):

自增锁是一种特殊类型的表锁,只要在事务对auto_increment类型的列插入数据时,才会施加auto-inc lock,此时其他想插入的事务都需要等待该锁的释放,而持有该锁的事务可以获得连续的primary key值。

在InnoDB存储引擎中,参数innodb_lock_wait_timeout用来控制锁的等待时间,默认值是50(秒)。

innodb_rollback_on_timeout控制超时时是否对事务进行回滚(默认是off,代表不回滚)。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值