我们知道,InnoDB是支持行锁,但不是每次都获取行锁,如果不使用索引的,那还是获取的表锁。而且有的时候,我们希望直接去使用表锁
在绝大部分情况下都应该使用行锁,因为事务的并发效率比表锁更高,但个别情况下也使用表级锁:
当我们希望获取表锁时,可以使用以下命令:

分析事务1获取行X锁和事务2获取表S锁:
首先事务1需要给表的第10行数据加X锁,于是InnoDB存储引擎自动给整张表加上了IX锁。当事务2再想获取整张表的S锁时,看到这张表已经有别的事务获取了IX锁了,就说明这张表肯定有某些数据被加上了X锁,这就导致事务2不能给整张表加S锁了。此时事务2只能等待,无法成功获取表S锁
MyISAM 表锁是 deadlock free 的, 这是因为 MyISAM 不支持事务,只支持表锁,而且总是一次获得所需的全部锁,要么全部满足,要么等待,因此不会出现死锁。如果是处理多张表,还是可能出现死锁问题的

在 InnoDB 中,除单个 SQL 组成的事务外,锁是逐步获得的,即锁的粒度比较小(行锁),这就决定了在 InnoDB 中发生死锁是可能的
死锁问题一般都是我们自己的应用造成的,和多线程编程的死锁情况相似,大部分都是由于我们多个线程在获取多个锁资源的时候,获取的顺序不同而导致的死锁问题。因此我们应用在对数据库的多个表做更新的时候,不同的代码段,应对这些表按相同的顺序进行更新操作,以防止锁冲突导致死锁问题
死锁出现的场景如下:
事务1成功获取行锁1
事务2成功获取行锁2
…
事务1无法获取行锁2,被阻塞的同时也无法释放行锁1
事务2无法获取行锁1,被阻塞的同时也无法释放行锁2

此时所有的事务都阻塞住了,相当于进程内的所有线程都阻塞住了,发生了死锁问题
解决死锁办法:多个事务/线程获取多个相同资源锁的时候应该按照同样的顺序获取锁。与此同时,由于mysqld(MySQL Server守护进程)设置了事务阻塞的超时时间,事务不会阻塞很长时间,超时后事务处理失败,自动释放当前占有的锁
设置自动提交 以及 可重复读隔离级别,开启事务

查询一下表数据,在可重复读隔离级别使用的是MVCC提供的快照读,并没有加锁

事务1获取id=7的排他锁,事务2获取id=8的排他锁

事务1再次获取id=8的排他锁,发生阻塞

事务2再次获取id=7的排他锁

此时由于MySQL Server检测到发生了死锁,于是解除事务1的阻塞,进行事务1的rollback,释放其占有的行锁,于是事务2成功获取id=7的排他锁
到此这篇关于一文学习MySQL 意向共享锁、意向排他锁、死锁的文章就介绍到这了,更多相关mysql意向共享锁、意向排他锁、死锁内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!