问题:
今天同事碰到了在mysql对表进行insert的时候报Lock wait timeout exceeded try restarting transaction的异常,在这里记录一下。
原因是update的时候给二级索引加了gap锁导致insert等待锁,再加上某个数据库节点有点异常,update更新慢,最终导致insert等待锁超时。gap锁是会锁住二级索引一定范围内的记录,这个时候要insert的时候落在这个范围内,就需要等待锁释放,update语句在长事务里或者执行慢了,insert就会出现所等待超时。
解决方法:
在update的时候where条件中尽量用主键id或者唯一索引。
关于gap锁:
1.间隙锁主要是防止幻象读,用在Repeated-Read(简称RR)隔离级别下,在Read-Commited(简称RC)下,一般没有间隙锁(有外键情况下例外,此处不考虑)。间隙锁还用于statement based replication。
2.间隙锁有些副作用,如果要关闭,一是将会话隔离级别改到RC下,或者开启 innodb_locks_unsafe_for_binlog(默认是OFF)。
3.间隙锁只会出现在辅助索引上,唯一索引和主键索引是没有间隙锁。间隙锁(无论是S还是X)只会阻塞insert操作。
更多资料可以参考:http://tech.meituan.com/innodb-lock.html
http://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html