14、MySQL锁等待排障

2021-05-12  本文已影响0人  一个反派人物

1 锁种类

1.1 Record lock

行锁,MySQL的行锁是通过索引加载,要是对应的SQL语句没有走索引,则会全表扫描,行锁无法实现,取而代之的是表锁,此时其它事务无法对当前表进行更新或插入操作。

1.2 GAP lock

间隙锁,锁的就是两个值之间的空隙,因此间隙锁只与往间隙里写入记录这个操作冲突,间隙锁只在隔离级别是可重复读隔离级别下才会生效。

1.3 Next-key lock

Record lock+GAP lock 锁定一个范围,并锁定记录本身,解决幻读。
唯一索引

非唯一索引

1.4 S Lock

共享锁:又称读锁,S锁与S锁兼容,可以同时放置。

1.5 X Lock

独占锁:又称排它锁、写锁。X锁不能和其他锁兼容,只要有事务对数据上加了任何锁,其他事务就不能对这些数据再放置X了,同时某个事务放置了X锁之后,其他事务就不能再加其他任何锁了,只有获取排他锁的事务是可以对数据进行读取和修改。

+代表兼容,-代表不兼容 X S
X - -
S - +

1.6 意向锁IX、IS

这是为了解决不同粒度的锁的兼容性判断而存在的。
因为锁的粒度不同,表锁的范围覆盖了行锁的范围,所以表锁和行锁会产生冲突,例如事务A对表中某一行数据加了行锁,然后事务B想加表锁,正常来说是应该要冲突的。如果只有行锁的话,要判断是否冲突就得遍历每一行数据了,这样的效率实在不高,因此我们就有了意向表锁。
意向锁的主要目的是为了使得行锁和表锁共存,事务在申请行锁前,必须先申请表的意向锁,成功后再申请行锁。意向锁是表级锁,但是却表示事务正在读或写某一行记录,而不是整个表, 所以意向锁之间不会产生冲突,真正的冲突在加行锁时检查。

意向锁分为意向读锁(IS)和意向写锁(IX)。

+代表兼容,-代表不兼容 IS IX S X
IS + + + -
IX + + - -
S + - + -
X - - - -

2 查看锁等待

SHOW STATUS LIKE 'innodb_row_lock%';
关注点:

3 查看等待锁和锁源的信息

3.1 查找出造成锁的连接线程

select * from sys.innodb_lock_waits\G;,找出blocking_pid

[(none)]>select * from sys.innodb_lock_waits\G;
*************************** 1. row ***************************
                wait_started: 2021-05-13 15:34:50
                    wait_age: 00:00:43
               wait_age_secs: 43
                locked_table: `test`.`t1`                           #出现锁的表
                locked_index: GEN_CLUST_INDEX                       #出现锁的索引
                 locked_type: RECORD                                #锁类型(record、gap、next-key)
              waiting_trx_id: 6927                                  #等待的事务id
         waiting_trx_started: 2021-05-13 15:34:50
             waiting_trx_age: 00:00:43
     waiting_trx_rows_locked: 1
   waiting_trx_rows_modified: 0
                 waiting_pid: 3                                     #等待的线程id
               waiting_query: update t1 set id=8 where id=1         #等待锁的sql语句
             waiting_lock_id: 6927:39:3:2
           waiting_lock_mode: X                                     #等待锁的类型(X、S)
             blocking_trx_id: 6926                                  #造成锁的事务id
                blocking_pid: 2                                     #造成锁的连接线程
              blocking_query: NULL
            blocking_lock_id: 6926:39:3:2
          blocking_lock_mode: X
        blocking_trx_started: 2021-05-13 15:34:15
            blocking_trx_age: 00:01:18
    blocking_trx_rows_locked: 3
  blocking_trx_rows_modified: 1
     sql_kill_blocking_query: KILL QUERY 2
sql_kill_blocking_connection: KILL 2
1 row in set, 3 warnings (0.01 sec)

3.2 查找出造成锁的SQL线程

select * from performance_schema.threads where processlist_id=2;processlist_id为上步找出的blocking_pid,找出THREAD_ID

3.3 查找出当前造成锁的SQL语句

select * from performance_schema.events_statements_current where thread_id=27\G;thread_id通过上一步找出,SQL_TEXT为具体的SQL语句

3.4 查找出历史造成锁的SQL语句

有时候当前造成锁的语句并不是造成锁的源头,这时候需要查询历史信息,查询锁的源头
select * from performance_schema.events_statements_history where thread_id=27\G;thread_id通过第2步找出,通过LOCK_TIMESQL_TEXT进行分析判断

4 死锁监控

show engine innodb status\G;
vim /etc/my.cnf
innodb_print_all_deadlocks=1
上一篇 下一篇

猜你喜欢

热点阅读