MySQL 等锁

MySQL 等锁

  • 查询长时间
    • 等 MDL 锁
    • 等 flush
    • 等行锁
  • 查询慢
  • 回滚查询

测试数据 :

CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `c` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

delimiter ;;
create procedure idata()
begin
  declare i int;
  set i=1;
  while(i<=100000)do
    insert into t values(i,i);
    set i=i+1;
  end while;
end;;
delimiter ;

call idata();

查询长时间

当查询结果长时间不返回 :

select * from t where id=1;

等 MDL 锁

看看当前语句的状态

show processlist
  • Waiting for table metadata lock : 有个线程正对表 t 持有 MDL 写锁,把 select 堵住

MySQL 等锁_第1张图片

MySQL 5.7 复现 :

  • session B 会进入等待状态
    | session A | session B |
    | — | — |
    | lock table t write; (MDL 写锁 ) | |
    | | select * from t where id = 1; (MDL 读锁) |

找出造成阻塞的 process id

select blocking_pid from sys.schema_table_lock_waits;

等 flush

查询 :

select * 
from information_schema.processlist 
where id=1;

查看该线程的状态 :

  • Waiting for table flush 状态 : 有个线程正对表 t 做 flush

image.png

对表 flush 操作 :

-- 只关闭表 t
flush tables t with read lock;

-- 关闭 MySQL 里所有打开的表
flush tables with read lock;

Waiting for table flush 复现 :

session A session B session C
select sleep(1) from t; (沉默)
flush tables t; (关闭 t 表)
select * from t where id = 1; (被 flush 堵住)

查看状态 :

show processlist;

MySQL 等锁_第2张图片

等行锁

当前读 :

  • id=1 记录,加读锁
select * from t 
where id=1 lock in share mode;

行锁复现 :

session A session B
begin;
update t set c= c+ 1 where id = 1;
select * from t whre id = 1 lock in share mode;

查看状态 :

show processlist;

MySQL 等锁_第3张图片

MySQL 5.7 能通过 sys.innodb_lock_waits 表查 :

select * from t sys.innodb_lock_waits 
where locked_table=`'test'.'t';
  • 是 4 号线程造成堵塞

MySQL 等锁_第4张图片

停止 4 号线程当前正在执行的语句

  • 无法去掉行锁
KILL QUERY 4

直接断开该连接

  • 连接断开 , 自动回滚 , 并释放行锁
KILL 4

查询慢

未走索引查询 :

select * from t 
where c = 50000 limit 1;

设置慢日志阈值 :

set long_query_time=0

慢查询日志 :

  • Rows_examined : 扫描了 50000 行
  • 查询花了 11.5 毫秒

image.png

回滚查询

查询一个值 :

select * from t where id=1;

慢日志 :

  • 扫描行数 1,但执行时间有 800 毫秒

image.png

当前读 :

select * from t 
where id=1 lock in share mode

慢日志 :

  • 扫描行数 1,执行时间 0.2 毫秒

image.png

查看执行结果 :

  • 查询结果 c=1
  • lock in share mode的查询 : c=1000001

MySQL 等锁_第5张图片

复现 :

session A session B
start transaction with consistent snapshot;
update t set c=c+1 wher id = 1; (执行 100w 次)
select * from t where id = 1;
select * from t wehre id = 1 lock in share mode;

session B 执行 100 万次 update 的结果 :

  • lock in share mode : 当前读,会直接读到 1000001 ,所以速度很快
  • select * from t where id=1 : 一致性读,要从 1000001 开始,依次执行 undo log,执行 100 万次后,才将 1 返回

MySQL 等锁_第6张图片

你可能感兴趣的:(MySQL,mysql,数据库,java,sql,开发语言)