Mysql 锁

本文深入解析数据库锁机制,包括InnoDB的行锁、表锁特性,读锁、写锁、意向锁和MDL锁的工作原理,以及如何监控和处理锁等待和死锁问题,提供实用的SQL查询语句。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据库的锁机制就是保证数据的一致性。

Innodb 支持行锁,有时会升级为表锁。

MyIsam:支持表锁

× 表锁的特点:

   开销小,加锁块;不会出现死锁,出现锁冲突的概率高,并发度相对低。

× 行锁特点:

开销大,加锁慢,会出现死锁现象;锁力度小,发生冲突的概率低。并发度相对高。

INNODB 的锁类型:

主要有读锁(共享锁)、写锁(排他锁)、意向锁和MDL 锁。

读锁: S锁。

可以同时读取同一行数据。但是在有读锁的情况下,不能进行修改。有读锁就不能获得写锁。

写锁: X锁

一个事务获取了一个数据行的写锁,其他事务就不能获取该行的其他锁,写锁优先级最高。

一些DML语句都会对行记录加写锁。

比较特殊的就是 select for update ,他会对读取的行增加一个写锁,那么其他的任何事物就不能加任何锁。

MDL锁

Mysql 5.5 引入了meta data lock,简称MDL锁,用于保证表中的元数据的信息。

意向锁:

在mysql 存储引擎INNODB中,意向锁是表锁。而且有两种意向锁的类型,分别为意向共享锁和意向排他锁。

意向共享锁(IS): 是指在给一个数据行加共享锁前必须先取得该表的IS锁。

意向排他锁(IX):是指在给一个数据行加排他锁前必须先取得该表的IX锁。

其实意向锁的作用跟MDL锁类似,都是防止数据的不一致。

锁等待和死锁

一个事务需要等待另一个事务释放它的锁后才能对对数据加锁。如果一上一个事务一直不释放,就需要持续等待下去。直到等待超时。

查看锁等的超时时间:

show variables like 'innodb_lock_wait_timeout';

死锁是指两个或两个以上的进程在执行过程中,因为争夺资源而造成一种等待的现象就是所谓的锁等待。即死循环。

 

监控锁状态及查询锁状态

1、看看有没有锁等待 

 show status like ‘inndob_row_lock%';

mysql> show status like 'innodb_row_lock%';
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| Innodb_row_lock_current_waits | 0     |  --------> 当前有多少锁等待
| Innodb_row_lock_time          | 0           |   -------->锁等待持续了多场时间   
| Innodb_row_lock_time_avg      | 0     |    ---------> 平均锁等待时间
| Innodb_row_lock_time_max      | 0     |   ----------> 最大锁等待时间
| Innodb_row_lock_waits         | 0     |        ---------->一共发生了多少次锁等待
+-------------------------------+-------+
 

2、查出那个事务在等待(被阻塞了)

use information_schema

select * from information_schema.INNODB_TRX where trx_state='LOCK WAIT';

trx_id: 事务ID

trx_state: 当前事务的状态

trx_mysql_thread_id: 连接层,连接线程ID(show processlist ===》ID 或 trx_id)

trx_query: 当前被阻塞的操作(一般是要丢给开发的)

 

3、查看锁源(看看谁站着茅坑不拉屎)

select × from sys.innodb_lock_waits;   #===========> 被锁的和锁定他的之间的关系

locked_table: 那张出现锁等待

waiting_trx_id:  等待的事务(与上个视图trx_id对应)

waiting_pid: 等待的线程号(与上一个试图trx_mysql_thread_id)

blocking_trx_id: 正在执行锁操作的事务ID

blocking_pid: 正在执行锁操作的线程号(show processlist)

 

4、找到锁源的thread_id (SQL线程)

select × from performance_schema.threads  where processlist_id=8;

===> 33 (SQL 线程ID)

5、找到锁源的SQL语句

select * from performance_schema.`events_statements_current`  where thread_id=33;

 

5.6 与5.7不同(5.6 没有sys库)

 

 

----执行语句的历史

select × from  performance_schema.events_statements_history where thread_id=41;

 

 

优化项目:锁的监控及处理

1、背景:

硬件环境: DELL R720 E系列16核, 48G MEM,SAS×900G ×6, RAID 10

在例行巡检时,发现9-11 点时间段cpu 压力非常高(80--90%)

2、项目的职责

     2.1 通过top 相信排查,发现mysqld 进程占比达到了700-800%

      2.2 其中cpu是的sys和wait比较高,us 处于正常

      2.3 怀疑是mysql 锁或者SQL语句除了问题。

      2.4 经过排查slow log 及锁等待情况,发现有大量锁等待及少量的慢语句。

            (1) pt-query-digest 查看慢查询日志

              (2)有没有锁等待

                       show status like 'innodb_row_lock%';

 

情况一: current_waits 说明当前很多锁等待

情况二: 1000多个lock_waits 说明历史上发生过的锁等很多

            2.5 查看那个事务在等待(谁被阻塞了)

            2.6 查看正在执行加锁的事务(谁锁的)

           2.7 找到锁源的thread_id

           2.8 找到锁源的SQL语句

 3.    找到语句之后与开发人员进行协商找出问题原因

       1、事务挂起导致的

       2、业务逻辑问题导致的死锁,产生了大量锁等待

          临时: kill

         最终: 修改代码中的业务逻辑

项目结果:

      经过排查出来,锁等待的个数减少80%,解决了cpu持续峰值的问题。

锁查询使用的命令:

show status like 'innodb_row_lock%';

select * from information_schema.innodb_trx;

select * from sys.innodb_lock_waits;

select * from performance_schema.threads;

select * from performance_schema.events_statements_cuurent;

select * from performance_schema.events_statements_history;

 

 

 

死锁监控:

show engine innodb status\G

show status like 'innodb_row_lock%';

vim /etc/my.cnf

innodb_print_all_deadlocks =1  #  把所有的死锁信息写入到error 日志里面。

 

死锁会产生严重的锁等待。

查出SQL 语句或者修改程序逻辑。

 

 

 

 

 

 

 

   

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

监控锁状态

1、查看没有锁等待

show status like 'innodb_row_lock%';

2、查看哪个事务在等待(被阻塞了)

use information_schema

select * from information_schema.INNODB_TRX where trx_state='LOCK WAIT';

trx_id:

trx_state:

trx_mysql_thread_id: 连接层的,连接线程id(show processlist )

trx_query

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值