MySQL(InnoDB剖析):31---锁之(锁的类型(共享锁、排它锁、意向锁)、查看锁的信息)

一、共享锁、排它锁

  • InnoDB实现了如下两种标准的行级锁:
    • 共享锁(S Lock):允许事务读一行数据
    • 排它锁(X Lock):允许事务删除或更新一行数据

锁之间的兼容性

  • 如果一个事务占用行r的共享锁:那么其他事务都可以立即获取这个共享锁,但是如果有的事务像获取排它锁就需要等待,等待对行r的共享锁全部被释放才可以

  • 如果你一个事务占用行r的排它锁:那么其他事务不论是占用改行的共享锁还是排他锁都需等待

  • 下图显示了共享锁和排它锁的兼容性:

二、意向锁

  • 此外,InnoDB存储引擎支持多粒度锁定,这种锁定允许事务在行级上的锁和表级上的锁同时存在。为了支持在不同力度上进行加锁操作,InnoDB存储引擎支持一种额外的锁定方式,称之为意向锁(Intention Lock)
  • InnoDB支持意向锁设计比较简单,其意向锁即为表级别的锁。设计目的主要是为了在一个事务中揭示下一行将被请求的锁类型
  • 其支持两种意向锁:
    • 意向共享锁(IS Lock):事务想要获得一张表中某几行的共享锁
    • 意向排它锁(IX Lock):事务想要获得一张表中某几行的排他锁

原理图解

  • 意向锁是将锁定的对象分为多个层次,意向锁意味着事务希望在更细粒度上进行加锁。如下图所示
  • 将上锁的对象看成一棵树,那么对最下层的对象上锁(也就是对最细粒度的对象进行上锁),那么首先需要对粗粒度的对象上锁
  • 例如:需要对页上的记录进行行上的X锁,那么分别需要对数据库、表、页上意向锁,最后对记录上X锁。若其中任何一个部分导致等待,那么该操作需要等待粗粒度锁的完成。
  • 例如:已经有事务对表进行了S表锁,此时想在对记录上加X锁,此时需要对表加IX锁,但是发现表已经加了S锁,因此需要等待表锁操作的完成

三、查看锁的信息

查看锁请求信息

  • 可以通过下面的信息查看当前锁请求的信息:
show engine innodb status\G
  •  可以看到SQL语句“select * from t where a<4 lock in share mode”在等待
  • RECORD LOCKS space id 30 page no 3 n bits 72 index 'PRIMARY' of table 'test'.'t' trx id 48B89BD lock_mode X locks rec but not gap表示锁住的资源
  • locks rec but not gap代表锁住的是一个索引,不是一个范围

  • 在InnoDB 1.0版本之前,用户只能通过命令SHOW FULL PROCESSLIST、SHOW ENGINE INNODB STATUS查看当前数据库中锁的请求,然后再判断事务锁的情况
  • 从InnoDB 1.0版本开始,在information_schema数据库下添加了表innodb_trx、innodb_locks、innodb_lock_waits。通过这三张表可以更简单地监控当前事务并分析可能存在的锁问题

innodb_trx表

  • 该表由8个字段组成:

  • 接下来看一个具体的例子:
    • 通过trx_state列观察到trx_id为730FEE的事务当前正在运行,而trx_id为7311F4的事务目前处于“LOCK WAIT”状态,且运行的SQL语句在trx_query中显示

  • innodb_trx表只是显示当前运行的InnoDB事务,并不能直接判断锁的一些情况

innodb_locks表

  • 如果需要查看锁,则还需要访问表innodb_locks表。该表的字段如下:

  • 接下来看一个具体的例子:
    • rx_id为730FEE的事务向表parent加了一个X的行锁,trx_id为7311F4的事务向表parent加了一个S的行锁
    • 两个事物都锁定了同一个行记录,且行记录的主键值为1,因此lock_data都是1,申请相同的资源,因此会等待

  • lock_data值的注意事项:lock_data这个值并非是“可信”的值。例如当用户运行一个范围查找时,lock_data可能只返回第一行的主键值。与此同时,如果当前资源被锁住了,若锁住的页因为InnoDB存储引擎缓冲池的容量,导致该页从缓冲池中被刷出,则查看innodb_locks表时,该值同样会显示为NULL,即InnoDB不会从磁盘进行再一次的查找

innodb_lock_wait表

  • 通过表innodb_locks查看了每张表上锁的情况后,用户可以来判断由此引发的等待情况了。当事务较小时,用户可以直观的看出,但是如果事务量非常大,其中锁和等待就非常多,此时不容易判断。但是通过表innnodb_lock_waits就可以反应出当前事务的等待
  • 该表有4个字段组成,含义如下:

  • 接下来看一个具体的例子:
    • ​​​​​​​例子中可以看到哪个事务阻塞了另一个事务

  • 当然,这里只给出了事务和锁的ID。如果想要观察更为详细的信息,可以进行下面的联合查询

发布了1462 篇原创文章 · 获赞 996 · 访问量 35万+

猜你喜欢

转载自blog.csdn.net/qq_41453285/article/details/104310571
今日推荐