首页 > 数据库 >MySQL行级锁初探

MySQL行级锁初探

时间:2023-04-11 22:35:42浏览次数:54  
标签:ENGINE 行级 LOCK MySQL 初探 performance connID ID schema

 

MySQL行级锁初探

 

版本:8.0.29

最近研究MySQL行级锁发现一个有趣的东东。

正常情况下,对于表级锁来说,对于会话持有某个表的锁(无论什么类型),可以在performance_schema.metadata_locks中查到会话持有锁的信息。

而对于会话对表的DML操作涉及的每一行,竟然都能在数据字典performance_schema.data_locks中查询到持有行锁的会话信息,这在Oracle中是没有的。

防爬虫:https://www.cnblogs.com/PiscesCanon/p/17308101.html 

 

如下:

开启两个会话connID=85(观察者)和connID=86(操作会话)。

connID=86查看测试表的信息,connID=85查看持有行锁会话信息:

connID=86:
(root@localhost 21:39:16) [performance_schema](86)> select count(*) from zkm.test where id=1234;
+----------+
| count(*) |
+----------+
|        2 |
+----------+
1 row in set (0.81 sec)

connID=85:
(root@localhost 21:39:22) [performance_schema](85)> SELECT * FROM performance_schema.data_locks WHERE LOCK_DATA is not null  \G
Empty set (0.00 sec)

 

 

其中,id=1234共两条数据,现在update这两条数据,再看看data_locks的信息:

connID=86:
(root@localhost 21:43:19) [performance_schema](86)> update zkm.test set id=1234 where id=1234;
Query OK, 0 rows affected (2.36 sec)
Rows matched: 2  Changed: 0  Warnings: 0

connID=85:
(root@localhost 21:44:32) [performance_schema](85)> SELECT * FROM performance_schema.data_locks WHERE LOCK_DATA is not null  \G
*************************** 1. row ***************************
               ENGINE: INNODB
       ENGINE_LOCK_ID: 139931197502248:409:1928:367:46912701287312
ENGINE_TRANSACTION_ID: 30127
            THREAD_ID: 318
             EVENT_ID: 123
        OBJECT_SCHEMA: zkm
          OBJECT_NAME: test
       PARTITION_NAME: NULL
    SUBPARTITION_NAME: NULL
           INDEX_NAME: GEN_CLUST_INDEX
OBJECT_INSTANCE_BEGIN: 46912701287312
            LOCK_TYPE: RECORD
            LOCK_MODE: X,REC_NOT_GAP
          LOCK_STATUS: GRANTED
            LOCK_DATA: 0x000001E93903
*************************** 2. row ***************************
               ENGINE: INNODB
       ENGINE_LOCK_ID: 139931197502248:409:1928:368:46912701287312
ENGINE_TRANSACTION_ID: 30127
            THREAD_ID: 318
             EVENT_ID: 123
        OBJECT_SCHEMA: zkm
          OBJECT_NAME: test
       PARTITION_NAME: NULL
    SUBPARTITION_NAME: NULL
           INDEX_NAME: GEN_CLUST_INDEX
OBJECT_INSTANCE_BEGIN: 46912701287312
            LOCK_TYPE: RECORD
            LOCK_MODE: X,REC_NOT_GAP
          LOCK_STATUS: GRANTED
            LOCK_DATA: 0x000001E93904
2 rows in set (0.00 sec)

 

可以看出,zkm.test的两行记录都有对应一条在performance_schema.data_locks的记录,可以看到持有行锁的会话的THREAD_ID之类的信息。

特别注意的是:LOCK_STATUS值为"GRANTED"才表示正持有锁。

 

保持上边会话update不commit,现在开多另外个会话connID=87,执行同一条update:

connID=87:
(root@localhost 21:46:29) [performance_schema](87)> update zkm.test set id=1234 where id=1234;
...等待...

connID=85:(排除connID=86会话的thread_id是318的信息)
(root@localhost 21:50:15) [performance_schema](85)> SELECT * FROM performance_schema.data_locks WHERE LOCK_DATA is not null and THREAD_ID!=318 \G
*************************** 1. row ***************************
               ENGINE: INNODB
       ENGINE_LOCK_ID: 139931197503056:409:1928:367:46912561630672
ENGINE_TRANSACTION_ID: 30128
            THREAD_ID: 319
             EVENT_ID: 120
        OBJECT_SCHEMA: zkm
          OBJECT_NAME: test
       PARTITION_NAME: NULL
    SUBPARTITION_NAME: NULL
           INDEX_NAME: GEN_CLUST_INDEX
OBJECT_INSTANCE_BEGIN: 46912561630672
            LOCK_TYPE: RECORD
            LOCK_MODE: X,REC_NOT_GAP
          LOCK_STATUS: WAITING
            LOCK_DATA: 0x000001E93903
1 row in set (0.01 sec)

 

LOCK_STATUS值为“WAITING”。

 

connID=87会话执行update被阻塞,单单从performance_schema.data_locks只知道想要持有某行的行锁而进入等待“WAITING”。

要查看查看等待的行锁阻塞和被阻塞这信息,需要查看:performance_schema.data_lock_waits(不推荐)或者sys.innodb_lock_waits

--根据实际情况可以添加where过滤数据
(root@localhost 22:07:54) [performance_schema](85)> select * from performance_schema.data_lock_waits \G
*************************** 1. row ***************************
                          ENGINE: INNODB
       REQUESTING_ENGINE_LOCK_ID: 139931197503056:409:1928:367:46912561630672
REQUESTING_ENGINE_TRANSACTION_ID: 30128
            REQUESTING_THREAD_ID: 319
             REQUESTING_EVENT_ID: 120
REQUESTING_OBJECT_INSTANCE_BEGIN: 46912561630672
         BLOCKING_ENGINE_LOCK_ID: 139931197502248:409:1928:367:46912701287312
  BLOCKING_ENGINE_TRANSACTION_ID: 30127
              BLOCKING_THREAD_ID: 318
               BLOCKING_EVENT_ID: 123
  BLOCKING_OBJECT_INSTANCE_BEGIN: 46912701287312
1 row in set (0.00 sec)

(root@localhost 22:07:55) [performance_schema](85)> SELECT * FROM sys.innodb_lock_waits\G
*************************** 1. row ***************************
                wait_started: 2023-04-11 21:46:33
                    wait_age: 00:21:24
               wait_age_secs: 1284
                locked_table: `zkm`.`test`
         locked_table_schema: zkm
           locked_table_name: test
      locked_table_partition: NULL
   locked_table_subpartition: NULL
                locked_index: GEN_CLUST_INDEX
                 locked_type: RECORD
              waiting_trx_id: 30128
         waiting_trx_started: 2023-04-11 21:45:22
             waiting_trx_age: 00:22:35
     waiting_trx_rows_locked: 4
   waiting_trx_rows_modified: 0
                 waiting_pid: 87
               waiting_query: update zkm.test set id=1234 where id=1234
             waiting_lock_id: 139931197503056:409:1928:367:46912561630672
           waiting_lock_mode: X,REC_NOT_GAP
             blocking_trx_id: 30127
                blocking_pid: 86
              blocking_query: NULL
            blocking_lock_id: 139931197502248:409:1928:367:46912701287312
          blocking_lock_mode: X,REC_NOT_GAP
        blocking_trx_started: 2023-04-11 21:39:19
            blocking_trx_age: 00:28:38
    blocking_trx_rows_locked: 2
  blocking_trx_rows_modified: 0
     sql_kill_blocking_query: KILL QUERY 86
sql_kill_blocking_connection: KILL 86
1 row in set (0.03 sec)

 

其中,对于sys.innodb_lock_waits来说,warting_pid=87&&blocking_pid=86表示会话87被86阻塞。

知道了86是始作俑者,就可以去对该会话做其他调查,看会话正在做什么,是否卡住或者被其他会话阻塞等。

 

对于元数据锁(其实就是表级锁)MDL,持有者信息可以查询performance_schema.metadata_locks,阻塞队列可以查询sys.schema_table_lock_waits。

而对于行级锁,持有者信息可以查询performance_schema.data_locks,阻塞队列可以查询performance_schema.data_lock_waits(不推荐)或者sys.innodb_lock_waits。

嗯,合理的雅痞。

 

 

参考文档:

How to Investigate InnoDB Lock Issues? (文档 ID 1531774.1)

 

标签:ENGINE,行级,LOCK,MySQL,初探,performance,connID,ID,schema
From: https://www.cnblogs.com/PiscesCanon/p/17308101.html

相关文章

  • 安装mysql
    在服务器下执行cd/usr/local,进入到local文件中。执行mkdirmysql创建文件夹。 mysql-8.0.22-1.el7.x86_64.rpm-bundle.tar文件拷贝到b服务器的/usr/local/mysql目录下。在b服务器cd/usr/local/mysql进入mysql文件夹,执行tar-xvfmysql-8.0.22-1.el7.x86_64.rpm-bundle.tar。......
  • Mysql主从同步
    1.配置主服务器#vi/etc/my.cnf[mysqld]character_set_server=utf8init_connect='SETNAMESutf8'#服务器唯一标识server_id=1#二进制日志文件名log-bin=master-binlog-bin-index=master-bin.indexport=3306重新启动主库#servicemysqlrestart在主数据库创......
  • mysql中字段存储不区分大小写
    mysql中查询时,遇到字段不区分大小写的情况,大小写都能取到值//sql语句中"select*fromtab_userwherebinaryusername=?andpassword=?";binary可以做到区分大小写//MySQL中默认字段是不区分大小写的,如果要完成区分大小写的功能,在设计时要注意字符集的选择......
  • pymysql 操作数据库
    一、数据库操作应用场景1、检验测试数据接口发送请求后明确会对数据库中的某个字段进行修改,但响应结果中无该字段数据时。如:ihrm删除员工接口。is_delete字段,没有在响应结果中出现!需要借助数据库校验!2、构造测试数据测试数据使用一......
  • python爬虫案列11:爬取双色球历史开奖记录并存储到mysql
    开始之前要先在MySQL创建一个名为spider的数据库,在里面创建一个名caipiao的表,表里面三个字段,data,red,blue点击查看代码importrequestsimportpymysqlfromlxmlimportetree#连接数据库conn=pymysql.connect(host='localhost',port=3306,user='root',password='......
  • 爬虫案列10:python 连接mysql
    importpymysql#打开数据库连接db=pymysql.connect(host='localhost',user='root',password='root',database='pikachu',port=3306......
  • mysql查询报表数据补全12个月
    mysql中生成多行序列1SELECT2SUBSTRING_INDEX(3SUBSTRING_INDEX('1,2,3,4,5,6,7,8,9,10,11,12',',',help_topic_id+1),',',-1)ROWNUM4FROM5mysql.help_topic6WHERE7help_topic_id<(LENGTH('1,2,3,4......
  • 力扣1107(MySQL)-每日新用户统计(中等)
    题目:Traffic表:该表没有主键,它可能有重复的行。activity列是ENUM类型,可能取(‘login’,‘logout’,‘jobs’,‘groups’,‘homepage’)几个值之一。问题编写一个SQL查询,以查询从今天起最多90天内,每个日期该日期首次登录的用户数。假设今天是2019-06-30.示例Tr......
  • R语言-连接MySQL数据库方法
    #2R语言-连接MySQL数据库方法#####2.1方法1:使用R数据库接口连接数据库#####使用RMySQL包install.packages('RMySQL')library(RMySQL)#有两种方式操作#2.1.1使用dbConnect####conn<-dbConnect(MySQL(),dbname="smartbi_data",        ......
  • 力扣1098(MySQL)-小众书籍(中等)
    题目:书籍表Books: book_id是这个表的主键订单表Orders:order_id是这个表的主键。book_id是Books表的外键。问题你需要写一段SQL命令,筛选出过去一年中订单总量少于10本的书籍。注意:不考虑上架(availablefrom)距今不满一个月的书籍。并且假设今天是2019-06-......