《丁奇-MySQL45讲-07/08》之归纳总结
07 | 行锁功过:怎么减少行锁对性能的影响
-
二阶段锁协议:在执行某条SQL时加锁,在事务提交后统一释放锁。 -
设置锁等待的超时时间:innodb_lock_wait_timeout,默认情况下是50秒。
-
发起死锁检测,innodb_deadlock_detect设置为on,默认情况下是on,缺点就是会耗费大量的CPU资源(发现死锁后主动回滚某一个事务,让其他事务得以继续执行)。
-
如果你的事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁的申请时机尽量往后放。
-
控制并发量不但可以减少死锁的概率,也可以减少死锁检测带来的性能消耗。
08 | 事务到底是隔离的还是不隔离的
之前总结丁琦老师第三篇文章的时候就已经总结了MVCC的概念,所以今天的文章中就不在对其进行重复总结,不过还是会说下丁奇老师对于MVCC的更为人性的总结。
-
很重要的一点,begin/start transaction命令并不是一个事务的起点,在执行到它们之后的第一个操作InnoDB表的语句后事务才正式开始,比如说select * from t。如果想要马上开启一个事务,可以使用start transaction with consistent snapshot命令。 -
简化下MVCC的分析过程:
-
版本未提交,不可见;
-
版本已提交,但是是在视图创建后提交的的,不可见;
-
版本已提交,但是是在视图创建前提交的,可见;
-
更新数据时读到的数据是当前读,所谓的当前读指的是数据的最新值,而快照读指的是数据的历史版本。 -
select语句如果加锁的话也是当前读,如select * from t where id = 1 lock in share mode或select * from t where id = 1 for update,前一种方式加的是共享锁(S),后一种加的是排它锁(X)。 -
图片直接摘抄丁奇老师的,我们都知道事务C没提交的情况下会阻塞事务B的更新,但我更好奇的是
事务A的查询语句会阻塞吗?一开始我认为是会,因为事务C`加的是排它锁,所以读也是会被阻塞的,但像事务A的查询语句并不会请求锁,所以我还是忍不住尝试了下,结果居然是不会阻塞(MySQL5.7),可能是因为查询语句要获取的是快照读,所以不会发生锁冲突...还是挺难说服自己的。

-
start transaction with consistent snapshot命令对于在RC隔离级别下的作用相当于start transaction,因为RC级别下每遇到一条语句就会生成新的ReadView。 -
思考题:要把所有"字段c和id值相等的行"的c值清零。

具体的流程说明:事务A先创建视图,随后事务B修改了k的值并提交,接着事务A执行更新语句,发现没有符合where条件的语句(被事务B抢先更新了),所以事务A的更新语句就失败了(记录上的事务ID没有发生改变),虽然事务B已经提交,但是是在事务A创建视图后提交的,是不可见的,所以事务A在查询的时候看到的仍然是原来的值,就出现了"明明值没有发生变化可我就是更新不了"的现象,这种场景就是所谓的乐观锁,通常情况下可以判断事务A是否执行失败了,如果失败了就重新发起一个事务,这样子就可以看到新值。

浙公网安备 33010602011771号