mysql中如何查看表是否被锁问题

目录
  • 如何查看是否发生死锁
  • 死锁发生情况及原因
    • 产生原因
    • 发生死锁的几种情况
  • 总结

如何查看是否发生死锁

在使用mysql的时候,如何查看表是否被锁呢?

查看表被锁状态和结束死锁步骤:

1.在mysql命令行执行sql语句

use dbName;  // 切换到具体数据库
show engine innodb status;  // 查询db是否发生死锁

2.查看数据表被锁状态

show OPEN TABLES where In_use > 0; 

该语句可以查询到当前锁表的状态

3.分析锁表的SQL

通过sql日志,分析相应SQL,给表加索引,常用字段加索引,表关联字段加索引等方式对sql进行优化。

4.查看正在锁的事务

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;

在5.5中,information_schema 库中增加了三个关于锁的表(innoDB引擎):

innodb_trx ## 当前运行的所有事务
innodb_locks ## 当前出现的锁
innodb_lock_waits ## 锁等待的对应关系

先来看一下这三张表结构:

root@127.0.0.1 : information_schema 13:28:38> desc innodb_locks;
+————-+———————+——+—–+———+——-+
| Field       | Type                | Null | Key | Default | Extra |
+————-+———————+——+—–+———+——-+
| lock_id     | varchar(81)         | NO   |     |         |       |#锁ID
| lock_trx_id | varchar(18)         | NO   |     |         |       |#拥有锁的事务ID
| lock_mode   | varchar(32)         | NO   |     |         |       |#锁模式
| lock_type   | varchar(32)         | NO   |     |         |       |#锁类型
| lock_table  | varchar(1024)       | NO   |     |         |       |#被锁的表
| lock_index  | varchar(1024)       | YES  |     | NULL    |       |#被锁的索引
| lock_space  | bigint(21) unsigned | YES  |     | NULL    |       |#被锁的表空间号
| lock_page   | bigint(21) unsigned | YES  |     | NULL    |       |#被锁的页号
| lock_rec    | bigint(21) unsigned | YES  |     | NULL    |       |#被锁的记录号
| lock_data   | varchar(8192)       | YES  |     | NULL    |       |#被锁的数据
+————-+———————+——+—–+———+——-+
10 rows in set (0.00 sec)

root@127.0.0.1 : information_schema 13:28:56> desc innodb_lock_waits;
+——————-+————-+——+—–+———+——-+
| Field             | Type        | Null | Key | Default | Extra |
+——————-+————-+——+—–+———+——-+
| requesting_trx_id | varchar(18) | NO   |     |         |       |#请求锁的事务ID
| requested_lock_id | varchar(81) | NO   |     |         |       |#请求锁的锁ID
| blocking_trx_id   | varchar(18) | NO   |     |         |       |#当前拥有锁的事务ID
| blocking_lock_id  | varchar(81) | NO   |     |         |       |#当前拥有锁的锁ID
+——————-+————-+——+—–+———+——-+
4 rows in set (0.00 sec)

root@127.0.0.1 : information_schema 13:29:05> desc innodb_trx ;
+—————————-+———————+——+—–+———————+——-+
| Field                      | Type                | Null | Key | Default             | Extra |
+—————————-+———————+——+—–+———————+——-+
| trx_id                     | varchar(18)         | NO   |     |                     |       |#事务ID
| trx_state                  | varchar(13)         | NO   |     |                     |       |#事务状态:
| trx_started                | datetime            | NO   |     | 0000-00-00 00:00:00 |       |#事务开始时间;
| trx_requested_lock_id      | varchar(81)         | YES  |     | NULL                |       |#innodb_locks.lock_id
| trx_wait_started           | datetime            | YES  |     | NULL                |       |#事务开始等待的时间
| trx_weight                 | bigint(21) unsigned | NO   |     | 0                   |       |#
| trx_mysql_thread_id        | bigint(21) unsigned | NO   |     | 0                   |       |#事务线程ID
| trx_query                  | varchar(1024)       | YES  |     | NULL                |       |#具体SQL语句
| trx_operation_state        | varchar(64)         | YES  |     | NULL                |       |#事务当前操作状态
| trx_tables_in_use          | bigint(21) unsigned | NO   |     | 0                   |       |#事务中有多少个表被使用
| trx_tables_locked          | bigint(21) unsigned | NO   |     | 0                   |       |#事务拥有多少个锁
| trx_lock_structs           | bigint(21) unsigned | NO   |     | 0                   |       |#
| trx_lock_memory_bytes      | bigint(21) unsigned | NO   |     | 0                   |       |#事务锁住的内存大小(B)
| trx_rows_locked            | bigint(21) unsigned | NO   |     | 0                   |       |#事务锁住的行数
| trx_rows_modified          | bigint(21) unsigned | NO   |     | 0                   |       |#事务更改的行数
| trx_concurrency_tickets    | bigint(21) unsigned | NO   |     | 0                   |       |#事务并发票数
| trx_isolation_level        | varchar(16)         | NO   |     |                     |       |#事务隔离级别
| trx_unique_checks          | int(1)              | NO   |     | 0                   |       |#是否唯一性检查
| trx_foreign_key_checks     | int(1)              | NO   |     | 0                   |       |#是否外键检查
| trx_last_foreign_key_error | varchar(256)        | YES  |     | NULL                |       |#最后的外键错误
| trx_adaptive_hash_latched  | int(1)              | NO   |     | 0                   |       |#
| trx_adaptive_hash_timeout  | bigint(21) unsigned | NO   |     | 0                   |       |#
+—————————-+———————+——+—–+———————+——-+
22 rows in set (0.01 sec)

5.查看等待锁的事务

SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS.

6.查看锁的类型和状态:

show status like '%lock%';

7.查询进程

show processlist

8.杀死发生死锁的进程

如果发生死锁,通过该语句可以查询到表被锁的进程,然后通过kill命令杀掉该进程。

其他查看表锁的情况:

# 查看表锁的情况:
mysql> show status like 'table%';
+----------------------------+---------+
| Variable_name | Value |
+----------------------------+---------+
| Table_locks_immediate | 100 |
| Table_locks_waited | 11 |
+----------------------------+---------+

# 查看InnoDB_row_lock状态变量来分析系统上的行锁的争夺情况:
mysql> show status like 'InnoDB_row_lock%';
+-------------------------------+--------+
| Variable_name                 | Value  |
+-------------------------------+--------+
| Innodb_row_lock_current_waits | 0      |
| Innodb_row_lock_time          | 159372 |
| Innodb_row_lock_time_avg      | 39843  |
| Innodb_row_lock_time_max      | 51154  |
| Innodb_row_lock_waits         | 4      |
+-------------------------------+--------+
5 rows in set (0.01 sec)

mysql>

在分析innodb中锁阻塞时,几种方法的对比情况:

  • (1)使用show processlist查看不靠谱;
  • (2)直接使用show engine innodb status查看,无法判断到问题的根因;
  • (3)使用mysqladmin debug查看,能看到所有产生锁的线程,但无法判断哪个才是根因;
  • (4)开启innodb_lock_monitor后,再使用show engine innodb status查看,能够找到锁阻塞的根因。

死锁发生情况及原因

产生原因

所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象。若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。表级锁不会产生死锁。所以解决死锁主要还是针对于最常用的InnoDB。

死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。

那么对应的解决死锁问题的关键就是:让不同的session加锁有次序

发生死锁的几种情况

会出现死锁的几种情况

我们有两张结构一模一样的表,分别为t1和t2:

id:integer
token:varchar
message:varchar

其中id是主键(自增),token是非聚集索引,message没有索引。

1、一张表两行记录交叉申请互斥锁

A执行到第二步时,等待B释放第一步的锁,而B需要执行完第二步结束事务之后才能释放锁;

B执行到第二步时,等待A释放第一步的速,这样A和B都无法进行下去,就产生了死锁现象。

2、两张表两行记录交叉申请互斥锁

这种情况与1中的类似。

3、聚集索引与非聚集索引冲突

这种不一定会产生死锁,表面上也看不出来。

假设A中满足条件的记录加锁顺序为(5,4,3,2,1),B中加锁顺序为(1,2,3,4,5),这里的排序是对应record的主键;

(InnoDB的锁是逐步获取的,而不是一次获取全部需要的锁。)

有可能A加锁了5和4,B加锁了1、2、3,再往下进行的话就会出相互等待陷入僵局的情况,就是死锁。

4、聚集索引冲突

这种情况与3中的类似。

5、间隙锁冲突

这种情况是因为A第一步使用了间隙锁,在A释放锁之前B第二步无法完成,也会形成死锁。

innodb提供了wait-for graph算法来主动进行死锁检测,每当加锁请求无法立即满足需要并进入等待时,wait-for graph算法都会被触发,检测是否出现等待环路。

当检测到死锁时,InnoDB会选择代价比较小的事务进行回滚。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Mysql锁机制之行锁、表锁、死锁的实现

    目录 一.Mysql锁是什么?锁有哪些类别? 二.行锁和表锁的区别 三.InnoDB死锁概念和死锁案例 死锁场景一之selectforupdate: 死锁场景二之两个update 四.程序开发过程中应该如何注意避免死锁 一.Mysql锁是什么?锁有哪些类别? 锁定义:    同一时间同一资源只能被一个线程访问    在数据库中,除传统的计算资源(如CPU.I/O等)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据

  • mysql查询表是否被锁的方法

    具体方法: (推荐教程:mysql数据库学习教程) 查看表被锁状态 # 查询哪些表锁了 show OPEN TABLES where In_use > 0; 查看造成死锁的sql语句 # 查询innodb引擎的运行时信息 show engine innodb status; 查询进程 # 查询所有进程 show processlist; 解锁(删除进程) # 删除进程 kill id; 查看正在锁的事物 # 查看正在锁的事物 SELECT * FROM INFORMATION_SCHEMA.IN

  • mysql中如何查看表是否被锁问题

    目录 如何查看是否发生死锁 死锁发生情况及原因 产生原因 发生死锁的几种情况 总结 如何查看是否发生死锁 在使用mysql的时候,如何查看表是否被锁呢? 查看表被锁状态和结束死锁步骤: 1.在mysql命令行执行sql语句 use dbName; // 切换到具体数据库 show engine innodb status; // 查询db是否发生死锁 2.查看数据表被锁状态 show OPEN TABLES where In_use > 0; 该语句可以查询到当前锁表的状态 3.分析锁表的SQL

  • mysql中如何查看表空间

    目录 mysql 查看表空间 mysql 临时表空间不足解决 查找思路以及解决方案 总结 mysql 查看表空间 主要是查看创建的库和系统自带的库大小  - SELECT table_schema,          concat(sum(round(data_length / (1024 * 1024), 2)), 'MB')  data_length,          concat(sum(round(index_length / (1024 * 1024), 2)), 'MB') ind

  • 图文详解Mysql中如何查看Sql语句的执行时间

    目录 一.初始SQL准备 二.Mysql查看Sql语句的执行时间 三.不同查询的执行时间 总结 Mysql中如何查看Sql语句的执行时间 一.初始SQL准备 初始化表 -- 用户表 create table t_users( id int primary key auto_increment, -- 用户名 username varchar(20), -- 密码 password varchar(20), -- 真实姓名 real_name varchar(50), -- 性别 1表示男 0表示

  • MySQL中的全表扫描和索引树扫描 的实例详解

    目录 引言 实例 引言 在学习mysql时,我们经常会使用explain来查看sql查询的索引等优化手段的使用情况.在使用explain时,我们可以观察到,explain的输出有一个很关键的列,它就是type属性,type表示的是扫描方式,代表 MySQL 使用了哪种索引类型,不同的索引类型的查询效率是不一样的. 在type这一列,有如下一些可能的选项: system:系统表,少量数据,往往不需要进行磁盘IOconst:常量连接eq_ref:主键索引(primary key)或者非空唯一索引(u

  • MySQL中dd::columns表结构转table过程及应用详解

    目录 一.MySQL的dd表介绍 二.代码跟踪 三.知识应用 四.总结 一.MySQL的dd表介绍 MySQL的dd表是用来存放表结构和各种建表信息的,客户端建的表都存在mysql.table和mysql.columns表里,还有一个表mysql.column_type_elements比较特殊,用来存放SET和ENUM类型的字段集合值信息.看一下下面这张表的mysql.columns表和mysql.column_type_elements信息.为了缩短显示长度,这里只展示几个重要的值. #建表

  • 浅谈MYSQL中树形结构表3种设计优劣分析与分享

    目录 简介 问题 设计1:邻接表 表设计 SQL示例 设计2:路径枚举 表设计 SQL示例 设计3:闭包表 表设计 SQL示例 结合使用 表设计 总结 简介 在开发中经常遇到树形结构的场景,本文将以部门表为例对比几种设计的优缺点: 问题 需求背景:根据部门检索人员, 问题:选择一个顶级部门情况下,跨级展示当前部门以及子部门下的所有人员,表怎么设计更合理 ? 递归吗 ?递归可以解决,但是势必消耗性能 设计1:邻接表 注:(常见父Id设计) 表设计 CREATE TABLE `dept_info01

  • MySQL数据库如何查看表占用空间大小

    目录 前言 1.切换数据库 2.查看所有数据库容量大小 3.查看指定数据库使用大小 4.查看表使用大小 5.查看所有数据库容量大小 6.查看所有数据库各表容量大小 7.查看指定数据库容量大小 8.查看指定数据库各表容量大小 总结 前言 CentOS7 安装MySQL8详细步骤 CentOS7 环境下MySQL常用命令 在mysql中有一个默认的数据表information_schema,information_schema这张数据表保存了MySQL服务器所有数据库的信息.如数据库名,数据库的表,

  • MySQL中如何重建表

    目录 1.删除表数据,为什么表文件大小不变 2.删除操作 3.新增操作 4.重建表 总结 1.删除表数据,为什么表文件大小不变 在日常开发中,你会发现当你删除表的数据后,整个数据库文件大小还是没有变化.这就是数据库表的空间回收问题. 首先我们还是针对 MySQL 中应用最广泛的 InnoDB 引擎展开讨论. 一个 InnoDB 表包含两部分,即:表结构定义和数据. 在 MySQL 8.0 版本以前,表结构是存在以.frm 为后缀的文件里. 而 MySQL 8.0 版本,则已经允许把表结构定义放在

  • 在MySQL中操作克隆表的教程

    可能有一种情况,当需要一个完全相同的副本表CREATE TABLE ... SELECT不适合需要,因为副本必须包含相同的索引,默认值,依此类推. 按下面的步骤,可以处理这种情况. 使用SHOW CREATE TABLE得到一个CREATE TABLE语句中指定源表的结构,索引等. 修改语句更改表名称的克隆表,并执行该语句.通过这种方式将有确切的克隆表. 或者,如果需要进行表的内容复制,使用INSERT INTO ... SELECT语句也可以搞定. 实例: 试试下面的例子来创建一个克隆表tut

  • MySQL中的回表和索引覆盖示例详解

    目录 索引类型 索引结构 非聚簇索引查询 索引覆盖 总结 索引类型 聚簇索引: 叶子节点存储的是行记录,每个表必须要有至少一个聚簇索引.使用聚簇索引查询会很快,因为可以直接定位到行记录 普通索引:二级索引,除聚簇索引外的索引,即非聚簇索引.普通索引叶子节点存储的是主键(聚簇索引)的值. 聚簇索引递推规则: 如果表设置了主键,则主键就是聚簇索引 如果表没有主键,则会默认第一个NOT NULL,且唯一(UNIQUE)的列作为聚簇索引 以上都没有,则会默认创建一个隐藏的row_id作为聚簇索引 索引结

随机推荐