死锁是指两个或两个以上的事务在执行过程中,因争夺锁资源而造成的一种相互等待的现象。
死锁产生的必要条件:
互斥:并发执行的事务为了进行必要的隔离保证执行正确,在事务结束前,需要对修改的数据库记录持锁,保证多个事务对相同数据库记录串行修改。
请求与保持:已经持有一个资源锁,等待另一个资源锁。
不剥夺:已经获得锁资源的事务,在执行前,不能强制剥夺,只能完成事务由自己释放。一般破坏该条件解除死锁,强制回滚。
循环等待:发生死锁时,必然存在一个事务,锁的环形链。调整sql顺序避免死锁。
MySQL锁:
加锁方式:
外部加锁:
共享锁(S):select * from table lock in share mode
排他锁(X):select * from table for update
内部加锁:
为了实现ACID特性,有数据库系统内部自动添加。
快照读:
Innodb实现多版本控制(MVCC),支持不加锁快照读。
select * from table where
保证同一个select结果集是一致的
不能保证同一事务内部,select语句与其他语句的数据一致性,如果需要,需要通过外部显示加锁。
当前读:
select...lock in share mode (共享读锁)
select...for update
update , delete , insert
当前读, 读取的是最新版本, 并且对读取的记录加锁, 阻塞其他事务同时改动相同记录,避免出现安全问题。
例如,假设要update一条记录,但是另一个事务已经delete这条数据并且commit了,如果不加锁就会产生冲突。所以update的时候肯定要是当前读,得到最新的信息并且锁定相应的记录。
分析死锁:show engine innodb status