1: 共享锁和排他锁,也称读锁和写锁。 读锁是不阻塞的,多个客户可以在同一个时刻读取同一资源,而不互相干扰。写锁是阻塞的,一个写锁会阻塞其他的写锁和读书。
2: 锁力度: 表锁,开销小,并发支持度低(相对于行锁); 行锁,开销大,并发支持度高。行锁在存储引擎层实现,而mysql 服务器层没有实现。
3: 事务的隔离级别:规定了一个事务内的修改,哪些是在事务内或者事务间是可见的,哪些是不可见的。事务是在存储引擎层实现的,所以同一个事务在多个存储引擎层之间操作是不可能的。
隔离级别 | 脏读 | 不可重复读可能性 | 幻读可能性 | 加锁读 |
Read Uncommited | yes | yes | yes | no |
Read Commited | no | yes | yes | no |
Repeatable Read | no | no | yes | no |
serializable | no | no | no | yes |
4: 死锁: 多个事务在同一资源上相互占用,请求锁定对方的占用的资源,从而导致恶性循环的现象。当多个事务试图以不同的顺序锁定同一资源的时候,就可能产生死锁。多个事务同时锁定同一个资源的时候,也会产生死锁。锁的行为和顺序是和存储引擎相关的的,innodb 存储引擎处理死锁的方式,是通过回滚持有最小行级排他锁的事物。
5: 多版本并发控制 MVCC
MVCC 可以理解为是行级锁的一个变种,但是它在很多情况下避免了加锁的操作,因此开销更低。虽然实现机制不同,但是大都实现了非堵塞的读操作,写操作也只锁定必要的行。mysql 的MVCC 解决了默认隔离级别 可重复读的幻读的情况。
Innodb MVCC 实现机制:是通过在每一个行末尾增加两个隐藏的列来实现。这两个列实际保存的是系统的版本号,一个是创建事务的版本号,一个是删除事务的版本号。 每个事务开启的版本号,是当前系统版本号自动递增。
MVCC 只在可重复读和提交读两个隔离级别下实现
疑问:
1: 读锁是共享锁,为什么还要加锁?
2:mysql 默认采用自动提交模式(auto commit),如果不是显示开启一个事务,则每一个查询都被当作一个事务执行提交操作。为什么这么做?开启事务难道不影响性能?
3: 死锁可以避免吗?减少死锁的方法有哪些?