尚硅谷Mysql高级day12(p54-62)

今天是2021-1-10。

一。表锁

1.偏向于MyISAM引擎,开销小,加锁快,发生锁冲突的概率较高。不会产生死锁,加锁的粒度较大,所以并发效率也较低
2.**show open tables;**查看所有库的锁
3.lock table 表名 read/write,给表添加读锁或者写锁
4.会话s1对book表加了读锁以后。s1可以查询book表的数据,不能修改book表的数据,并且也不能对s1会话中的其他表进行任何操作。此时s2可以操作其他没有加锁的表,也可以查询book表的数据,但是如果去更新book表的数据,则必须一直阻塞等待s1释放掉对book的读锁,才能进行操作。
5.会话s1对book表加了写锁以后。s1可以查询book表的数据,也能修改book表的数据,但不能对s1会话中的其他表进行任何操作。s2查询或者更新book表的数据,需要一直阻塞等待s1释放写锁,可以操作其他没有加锁的表
6.MyIASM引擎,在执行select语句之前,会对目标表加读锁。执行增删改操作之前。会对目标表加写锁

二。行锁

1.偏向于InnoDB引擎,开销较大,加锁慢,会出现死锁,加锁的粒度较小,发生锁冲突的概率较低,并发效率较高。
2.InnoDB支持事务,默认的隔离级别为可重复读。此时我们有两个会话s1和s2,都关闭了事务自动提交,s1对记录1的字段a加了100并提交,s2在不提交时,只能读到a的原值,提交后才能读到a+100后的值。
3.行读锁S:当一个事务读取一条记录的时候,不会阻塞其他事务对同一记录的读请求,但会阻塞对其的写请求。当读锁释放后,才会执行其他事务的写操作。
4.行写锁X:当一个事务对一条记录进行写操作时,会阻塞其他事务对同一表的读写操作,当该锁释放后,才会执行其他事务的读写操作。
5.如果多个事务都去更新同一行记录,会造成性能问题,可以通过 innodb_lock_wait_timeout 来解决。innodb_lock_wait_timeout 是事务等待获取资源的最长时间,单位为秒。如果超过时间还未分配到资源,则会返回应用失败。
6.注意,innoDB在试图给一行记录上行锁之前,必须先获得记录所在表的同类型锁,比如给行1上行读锁,那么就得先获取表读锁。表读锁即IS,表写锁即IX
7.注意,如果sql语句中的字段没有使用到索引,那么InnoDB就无法通过索引给对应的记录加行锁,需要全表扫描,就会导致原本的行锁升级为表锁,影响其他事务对表的操作,所以字段尽量使用索引。

三。间隙锁

当使用范围条件索引数据时,对于需要加锁的一行记录,InnoDB 会对符合条件的数据索引项加锁。对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB 也会对这个“间隙”加锁,这就是间隙锁。间隙锁和行锁合称(Next-Key锁)。
比如s1执行了一条sql:....where a>1 and a<6,然后尚未提交事务。此时另一个事务s2希望插入a=2的一条记录,但是此时字段a没有2这个值,所以s2这个插入操作进入阻塞等待s1释放锁。
可以说间隙锁也保证了数据的一致性,对于上例来说,如果在还没提交事务之前,s2插入了本不存在的记录,s1再次执行select语句,就会产生幻读。

四。锁的优化建议

1.尽可能让数据检索通过索引完成,避免 InnoDB 因为无法通过索引加行锁,而导致升级为表锁的情况。换句话说就是,多用行锁,少用表锁。
2.加索引的时候尽量准确,避免造成不必要的锁定影响其他查询。
3.尽量减少给予范围的数据检索(间隙锁),避免因为间隙锁带来的影响,锁定了不该锁定的记录。
4.尽量控制事务的大小,减少锁定的资源量和锁定时间。
5.尽量使用较低级别的事务隔离,减少 MySQL 因为事务隔离带来的成本。

五。页锁

开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

六。总结

主从复制目前还用不太到,就结束了,跟着阳哥一路走下来也是收获良多,至于主从复制,以后负责数据库这方面再看吧。实习了以后,这也是毕业之前最后一个自己自主去学习的东西了,接下来就是根据公司的需求去学习了,redis、kafka见。
2021-1-10 20:59

猜你喜欢

转载自blog.csdn.net/qq_44727091/article/details/112428196