重新认识Database-MySQL⑤--锁机制

122 阅读2分钟

锁分类

  • 性能分有乐观锁和悲观锁,前者适用读操作较多的业务,后者适用写操作较多的业务.
  • 操作分有行锁,表锁.
  • 数据库操作类型有读锁和写锁(都属于悲观锁)

乐观锁

只是在执行更新的时候判断一下在此期间别人是否修改了数据:如果别人修改了数据则放弃操作,否则执行操作(一般都是用version)

悲观锁

操作数据时直接把数据锁住,直到操作完成后才会释放锁;上锁期间其他人不能修改数据

表锁

操作锁住整张表.开销小,加锁快;锁力度大,锁的冲突概率越高,并发度较低;一般用在表的数据迁移

-- 锁表,主要是迁移的时候,防止数据增加
lock table users read;
-- 查看表锁
show open tables where in_use>=1;
-- 删除表锁
unlock tables;

在锁表的过程中,不能修改表数据

image.png

行锁

锁住一行数据.开销大,加锁慢(需要遍历到该数据);锁粒度小,锁冲突较低,并发度高

InnoDB行锁实际上是在索引对应的项上做标记;如果该索引失效或者删除,就会升级行锁为表锁(RR级别会升级,RC不会)

升级的大致原因

RR级别需要解决不可重复读以及幻读问题,所以为了防止索引被其他事务修改(不可重复读)或被其他事务新增记录(幻读--主要在间隙中新增),从而导致数据问题,MySQL解决方案扫描索引记录和间隙都上锁.

间隙锁

顾名思义,间隙就是两值间的空隙,只在可重复读(repeattable-read)的隔离级别下才会生效.综合来讲就是间隙锁能在可重复读下解决幻读问题.

开启可重复读

-- 可重复读
set tx_isolation='repeatable-read';
begin;
select * from users;
commit;

间隙可知(3,20) image.png

故在(3,20)间插入数据,就会出现数据等待 image.png

间隙就是锁住该数据的间隙范围,防止插入数据,解决幻读问题.

锁等待

执行innodb_row_lock变量来分析

-- 锁状态分析
show status like 'innodb_row_lock%';

image.png

主要关注 lock_time_avg 等待平均时长 lock_waits 等待总次数 lock_time 等待总时长

等待次数很高,等待时长也挺长,需要根据分析着手制定优化计划.

查看information_schema系统锁表


-- 查看事务
SELECT * from information_schema.INNODB_TRX;
-- 查看锁,8后换成data_locks
SELECT * from information_schema.INNODB_LOCKS;
-- 查看锁等待,8后换成 data_lock_waits
SELECT * from information_schema.INNODB_LOCK_WAITS;
-- 释放锁.trx_mysql_thread_id,从INNODB_TRX 查看
kill trx_mysql_thread_id;
-- 查看锁详细情况
show engine innodb statsu