mysql_阻塞和死锁
什么是阻塞
由于不同锁之间的兼容关系,造成一个事务需要等待另一个事务释放其所占用的资源的现象 称为 阻塞
如何发现阻塞
mysql_8.0
SELECT waiting_pid as '被阻塞的线程',
waiting_query as '被阻塞的SQL',
blocking_pid as '阻塞线程',
blocking_query as '阻塞SQL',
waiting_age as '阻塞时间',
sql_kill_blocking_query as '建议操作'
FROM
sys.innodb_lock_waits
WHERE
( UNIX_TIMESTAMP() - UNIX_TIMESTAMPP(wait_started) ) > 30;
这里的 30 是三十秒的意思
如何处理阻塞
- 终止占用资源的事务(治标不治本)
- 优化占用资源事务的SQL,使其尽快释放资源
什么是死锁
并行执行的多个事务相互之间占有了对方所需要的资源
比如:
事务一
BEGIN;
Update course set score = 9.7 where course_id = 35;
update user set score = score - 10 where user_id = 10;
事务二
BEGIN;
update user set score = score + 10 where user_id = 10;
Update course set score = 9.8 where course_id = 35;
由于事务一和事务二 where条件一致,在一定的条件下会导致死锁,比如事务一在执行第一条sql时对该资源加排他锁,同时事务二对另一资源加上了排他锁,当两个事务在执行它们的第二条SQL时,会分别等待对方的排他锁释放,导致死锁发生
如何发现死锁
将死锁记录到错误日志中
set global innodb_print_all_deadlocks = on;
死锁日志例子(整理后):
TRANSACTION 1704, ACTIVE 119 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 4 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MYSQL thread id 12, OS thread handle 14025222817xxxxx, query id 170 localhost root update
update imc_user set score = score + 10 where user_id = 10
这里记录的可能不是导致产生死锁的那个SQL, 而是事务中发生死锁时正在执行的那个SQL,所以还是根据这个线索去程序中寻找问题的症结所在