首页 > 数据库 >【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)

【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)

时间:2023-04-03 20:40:55浏览次数:43  
标签:27 表级 会话 线程 虚竹 SQL id schema


回城传送–》《32天SQL筑基》

文章目录

  • 零、前言
  • 一、什么是表级锁
  • 二、什么时候适合加表级锁
  • 三、实战演练
  • 3.1 数据准备(如果已有数据可跳过此操作)
  • 3.2 开启第一个会话,执行显式加表级锁
  • 3.3 开启第二个会话,对该表执行update更新
  • 3.4 开启第三个会话,查询线程信息
  • 3.5 分析
  • 3.6 释放第一个会话的表读锁
  • 四、总结
  • 五、参考

零、前言

今天是学习 SQL 打卡的第 27 天,每天我会提供一篇文章供群成员阅读( 不需要订阅付钱 )。

希望大家先自己思考,如果实在没有想法,再看下面的解题思路,自己再实现一遍。在小虚竹JAVA社区 中对应的 【打卡贴】打卡,今天的任务就算完成了,养成每天学习打卡的好习惯。

虚竹哥会组织大家一起学习同一篇文章,所以有什么问题都可以在群里问,群里的小伙伴可以迅速地帮到你,一个人可以走得很快,一群人可以走得很远,有一起学习交流的战友,是多么幸运的事情。

我的学习策略很简单,题海策略+ 费曼学习法。如果能把这些题都认认真真自己实现一遍,那意味着 SQL 已经筑基成功了。后面的进阶学习,可以继续跟着我,一起走向架构师之路。

今天的学习内容是:SQL进阶-查询优化- performance_schema系列实战二:锁问题排查(表级锁)

一、什么是表级锁

表级锁是MySQL中对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MYISAM与INNODB都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)。
特点:开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。

二、什么时候适合加表级锁

1、事务需要更新某张大表的大部分或全部数据。如果使用默认的行锁,不仅事务执行效率低,而且可能造成其它事务长时间锁等待和锁冲突,这种情况下可以考虑使用表锁来提高事务执行速度;

2、事务涉及多个表,比较复杂,可能会引起死锁,导致大量事务回滚,可以考虑表锁避免死锁。

3、表级锁更适合于以查询为主,并发用户少,只有少量按索引条件更新数据的应用,如Web 应用

其中表锁又分为表读锁和表写锁,命令分别是:
表读锁:

lock tables 表名 read;

表写锁:

lock tables 表名  write;

解锁:释放锁只能释放我们手动使用LOCK 加的锁, 不能释放死锁等其他情况的事物锁等

UNLOCK TABLES;

三、实战演练

通过一个示例演示如何找出谁持有表级锁。

3.1 数据准备(如果已有数据可跳过此操作)

使用sysbench准备初始化数据
创建测试数据库sysbenchdemo

create database sysbenchdemo;

【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)_读锁


准备测试数据:

sysbench /usr/share/sysbench/oltp_insert.lua \
--mysql-host=localhost \
--mysql-port=3306 \
--mysql-socket=/tmp/mysql.sock \
--mysql-user=root \
--mysql-password=xiaoxuzhu \
--mysql-db=sysbenchdemo \
--db-driver=mysql \
--tables=8 \
--table-size=100000 \
--time=180 prepare

【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)_数据库_02

3.2 开启第一个会话,执行显式加表级锁

登录mysql数据库

use sysbenchdemo;

【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)_sql_03

查询以下加锁线程的process id,以便后续排查过程好对应

select connection_id();

【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)_mysql_04

对sbtest1 表加表读锁

lock table sbtest1 read;

【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)_数据库_05

3.3 开启第二个会话,对该表执行update更新

登录mysql数据库

use sysbenchdemo;

【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)_sql_03

查询线程的process id,以便后续排查过程好对应

select connection_id();

【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)_SQL_07

对该表执行update更新

update sbtest1 set pad='xxx' where id=1;

发现执行更新语句被阻塞。

【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)_读锁_08

3.4 开启第三个会话,查询线程信息

show processlist;

【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)_mysql_09


可以发现update语句在等待MDL锁(Waiting for table metadata lock)

其中OWNER_THREAD_ID: # 持有锁的内部线程ID

查看process id为 12442,12443 各自对应的内部线程ID是多少

select sys.ps_thread_id(12442);

【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)_sql_10

process id=12442 的线程对应的内部线程ID正好为12606

select sys.ps_thread_id(12443);

【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)_数据库_11

process id=12443 的线程对应的内部线程ID正好为12607

3.5 分析

因为是等待MDL锁,所以先看看performance_schema.metadata_locks表,记录的顺序代表持有锁的时间顺序

select * from performance_schema.metadata_locks where OWNER_THREAD_ID!=sys.ps_thread_id(connection_id());

【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)_SQL_12

如下就是MDL相关的锁模式,以及对应的SQL语句

锁模式

对应SQL

MDL_INTENTION_EXCLUSIVE

GLOBAL对象、SCHEMA对象操作会加此锁

MDL_SHARED

FLUSH TABLES with READ LOCK

MDL_SHARED_HIGH_PRIO

仅对 MyISAM 存储引擎有效

MDL_SHARED_READ

SELECT查询

MDL_SHARED_WRITE

DML语句

MDL_SHARED_WRITE_LOW_PRIO

仅对MyISAM存储引擎有效

MDL_SHARED_UPGRADABLE

ALTER TABLE

MDL_SHARED_READ_ONLY

LOCK xxx READ

MDL_SHARED_NO_WRITE

FLUSH TABLES xxx,yyy,zzz READ

MDL_SHARED_NO_READ_WRITE

FLUSH TABLE xxx WRITE

MDL_EXCLUSIVE

ALTER TABLE xxx PARTITION BY …

从图上可知,LOCK_TYPE 为SHARED_READ_ONLY的12606 内部线程手动加了表读锁;

确认一下线程是否存在着一个没有提交的事务。

select * from information_schema.innodb_trx;

【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)_sql_13

发现没有记录。

可以尝试着去查询一些表级别的锁信息(通过会话3查询performance_schema.table_handles表)

select * from performance_schema.table_handles where OWNER_THREAD_ID=12606;

【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)_SQL_14

证实了12606 内部线程手动加了表读锁;但还是不知道该线程执行了什么SQL语句,可以通过performance_schema.events_statements_current表查询。

select * from performance_schema.events_statements_current where thread_id=12606;

【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)_sql_15

通过SQL_TEXT字段我们可以清晰地看到该线程正在执行的SQL语句是什么。

3.6 释放第一个会话的表读锁

UNLOCK TABLES;

【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)_sql_16

第二个会话被阻塞的语句也顺利执行了。

【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)_mysql_17

在第三个会话中查看线程情况

show processlist;

【第27天】SQL进阶-查询优化- performance_schema系列实战三:锁问题排查(表级锁)(SQL 小虚竹)_SQL_18

从图上结果可知,MDL锁被释放了。

四、总结

通过本文学习,学会了什么是表级锁以及表级锁的适用场景,通过实战演练排查表级锁问题,从理论到实战的介绍,可以加深对表级锁的理解。

五、参考

应用示例荟萃 | performance_schema全方位介绍(中)技术分享 | MySQL 的 MDL 锁解惑
SQL进阶-查询优化- performance_schema系列三:事件记录(SQL 小虚竹)

我是虚竹哥,我们明天见~


标签:27,表级,会话,线程,虚竹,SQL,id,schema
From: https://blog.51cto.com/u_14122613/6167355

相关文章

  • MySQL实战45讲 笔记
    笔记不要小看一条update语句,在生产机上使用不当可能会导致业务停滞,甚至崩溃。当我们要执行update语句的时候,确保where条件中带上了索引列,并且在测试机确认该语句是否走的是索引扫描,防止因为扫描全表,而对表中的所有记录加上锁。我们可以打开MySQL里的sql_safe_updates参数......
  • MySQL索引详细介绍
    一、什么是索引?为什么要建立索引?索引用于快速找出在某个列中有一特定值的行,不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多,如果表中查询的列有一个索引,MySQL能够快速到达一个位置去搜索数据文件,而不必查看所有数据,那么将会节省很......
  • POJ 2773 Happy 2006 二分+容斥原理(二进制枚举或dfs)
    Happy2006TimeLimit: 3000MS MemoryLimit: 65536KTotalSubmissions: 14003 Accepted: 4946DescriptionTwopositiveintegersaresaidtoberelativelyprimetoeachotheriftheGreatCommonDivisor(GCD)is1.Forinstance,1,3,5,7,9...areallrelativel......
  • mysql多实例配置
    实现在一台服务器上开两个数据库服务。配置:[mysqld_multi]user=rootmysqld=/usr/local/mysql/bin/mysqld_safemysqladmin=/usr/local/mysql/bin/mysqladmin[mysqld1]datadir=/dir1port=3307pid-file=/dir1/mysqld1.pidlog-error=/dir1/mysqld1.errsocket=/dir1/mysqld1.sock[mysqld......
  • 高可靠myql配置-双MysqlRouter+MHA
    普通的主备方案 双MysqlRouter+MHA  3.1资源角色 主机IP 软件版本 备注RouterMaster 192.10.13.203 8.0.16 192.10.13.205RouterSlave 192.10.13.204 8.0.16 192.10.13.205MHAManager 192.10.13.206 MHA0.56 MHANode&Mysql主 192.10.13.201 MHA0.56&My......
  • PL/SQL 基础---复杂数据类型和自定义类型
    原文地址:https://blog.csdn.net/villare/article/details/53437924PL/SQL基础—复杂数据类型和自定义类型PLSQL中常用的自定义类型就两种:记录类型、PLSQL内存表类型(根据表中的数据字段的简单和复杂程度又可分别实现类似于简单数组和记录数组的功能)除此之外,还有大对象类型:CLOB......
  • ansible 部署mysql 5.7
    准备工作创建roles目录#mkdir-pv/data/apps/ansible/roles/mysql-5.7/{files,tasks,handlers,templates,vars}hosts[ubuntu]172.16.18.31ansible_ssh_port=22ansible_ssh_user=ubuntuhostname=app-01测试连通性#ansibleubuntu-mping172.16.18.247|SUCCESS=......
  • MySQL 关闭 binlog 日志
    【关闭binlog日志】1、vim/etc/my.cnf注释如下内容:#log-bin=mysql-bin#binlog_format=mixed#server-id=1#expire_logs_days=102、重启mysql服务/etc/init.d/mysqlrestart......
  • MySQL实现over partition by(分组后对组内数据排序)
     开发中遇到了这样一个需求:统计商品库存,产品ID+子产品名称都相同时,可以确定是同一款商品。当商品来自不同的渠道时,我们要统计每个渠道中最大的那一个。如果在Oracle中可以通过分析函数OVER(PARTITIONBY…ORDERBY…)来实现。在MySQL中应该怎么来实现呢。现在通过两种......
  • YUM安装MySQL 8.0
     安装官方yumrpm-ivhhttps://repo.mysql.com//mysql57-community-release-el7-9.noarch.rpm 调试yum关闭旧版本yum-config-manager--disablemysql57-community开启新版本yum-config-manager--enablemysql80-community安装mysql8.0yuminstallmysql-co......