死锁的情况发生在不同的的事务相互之间拥有对方需要的锁,而导致相互一直无限等待。死锁可能发生在不同的事务都会对多个相同的表和相同的行上施加锁,但事务对表的操作顺序不相同。
为了减少死锁的发生,要避免使用lock
table语句,要尽量让修改数据的范围尽可能的小和快速;当不同的事务要修改多个表或者大量数据时,尽可能的保证修改的顺序在事务之间要一致。默认情况下InnoDB下的死锁自动侦测功能是开启的,当InnoDB发现死锁时,会将其中的一个事务作为牺牲品回滚。
通过innodb_lock_wait_timeout参数配置自动侦测功能是否开启,如果关闭的话,InnoDB就会使用innodb_lock_wait_timeout参数来自动回滚等待足够时间的事务。可以通过show
engine innodb status语句查看最后一次发生死锁的情况。
InnoDB死锁检测和回滚?默认情况下死锁检测功能是开启的,当死锁发生时InnoDB会自动检测到并牺牲其中的一个或者几个事务,以便让其他的事务继续执行下去。InnoDB选择牺牲的事务往往是代价比较小的事务,其代价计算是根据事务insert,update,
delete的数据行规模决定。如果事务中的某个语句因为错误而回滚,则这个语句上的锁可能还会保留,是因为InnoDB仅会存储行锁信息,而不会存储行锁是由事务中的哪个语句产生的。如果在一个事务中,select语句调用了函数,而函数中的某个语句执行失败,则那个语句会回滚,如果在整个事务结束时执行rollback,则整个事务回滚。可以通过innodb_deadlock_detect
参数关闭死锁检测功能,而仅仅用innodb_lock_wait_timeout的功能来释放锁等待 。
那么,减少死锁发生的方法有什么呢?
在事务性数据库中,死锁是个经典的问题,但只要发生的频率不高则死锁问题不需要太过担心。查看死锁的方法有两种:1.通过show engine innodb
status命令可以查看最后一个死锁的情况。2.通过innodb_print_all_deadlocks参数配置可以将所有死锁的信息都打印到MySQL的错误日志中。
减少死锁发生的方法:1.尽可能的保持事务小型化,减少事务执行的时间可以减少发生影响的概率;2.及时执行commit或者rollback,来尽快的释放锁;3.可以选用较低的隔离级别,比如如果要使用select...for
update和select...lock in share
mode语句时可以使用读取提交数据隔离级别;4.当要访问多个表数据或者要访问相同表的不同行集合时,尽可能的保证每次访问的顺序是相同的。比如可以将多个语句封装在存储过程中,通过调用同一个存储过程的方法可以减少死锁的发生。
互联网企业大多用的数据库是MySQL的,想要众多的IT工作者中脱颖而出,就需要拥有高深的技术,学习增值是必不可少的。学习之路,是贵在坚持的。老男孩教育MySQL
DBA课程,几经更新课程,杜绝纸上谈兵,全企业真实案例结合理论授课,想深入的学习MySQL DBA的知识,可以关注下老男孩教育。
原文地址:http://blog.51cto.com/13543192/2119575