转载部分

Mysql中各种锁的理解

2019-03-05  本文已影响103人  哪吒小子

一:引言--为什么mysql提供了锁

最近看到了mysql有行锁和表锁两个概念,越想越疑惑。为什么mysql要提供锁机制,而且这种机制不是一个摆设,还有很多人在用。在现代数据库里几乎有事务机制,ACID的机制应该能解决并发调度的问题了,为什么还要主动加锁呢?

二:MySQL的事务机制

理解MySql事务隔离机制、锁以及各种锁协议:https://blog.csdn.net/gklifg/article/details/38752691

数据库的acid属性

原性性(Actomicity):事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。
一致性(Consistent):在事务开始和完成时,数据都必须保持一致状态。这意味着所有相关的数据规则都必须应用于事务的修改,以操持完整性;事务结束时,所有的内部数据结构(如B树索引或双向链表)也都必须是正确的。
隔离性(Isolation):数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行。这意味着事务处理过程中的中间状态对外部是不可见的,反之亦然。
持久性(Durable):事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。

事务并发调度的问题

脏读(dirty read):A事务读取B事务尚未提交的更改数据,并在这个数据基础上操作。如果B事务回滚,那么A事务读到的数据根本不是合法的,称为脏读。在oracle中,由于有version控制,不会出现脏读。
不可重复读(unrepeatable read):A事务读取了B事务已经提交的更改(或删除)数据。比如A事务第一次读取数据,然后B事务更改该数据并提交,A事务再次读取数据,两次读取的数据不一样。
幻读(phantom read):A事务读取了B事务已经提交的新增数据。注意和不可重复读的区别,这里是新增,不可重复读是更改(或删除)。这两种情况对策是不一样的,对于不可重复读,只需要采取行级锁防止该记录数据被更改或删除,然而对于幻读必须加表级锁,防止在这个表中新增一条数据。
第一类丢失更新:A事务撤销时,把已提交的B事务的数据覆盖掉。
第二类丢失更新:A事务提交时,把已提交的B事务的数据覆盖掉。

三: MySQL的行锁和表锁

表级锁:每次操作锁住整张表。开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低;
行级锁:每次操作锁住一行数据。开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高;
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

MySQL中我们可以在select语句最后加FOR UPDATE来对所查询的行加锁.
通过使用 for update可以对数据加写锁
必须在begin/commit或者autocommit=0的情况下
如果where条件中只用到索引项,则加的是行锁;否则加的是表锁。

MySQL中的乐观锁和悲观锁

悲观锁(Pessimistic Concurrency Control,PCC):假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。至于怎么加锁,加锁的范围也没讲。

乐观锁(Optimistic Concurrency Control,OCC):假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。也没具体指定怎么检查。

参考文献

mysql的锁--行锁,表锁,乐观锁,悲观锁:https://www.cnblogs.com/deliver/p/5730616.html
mysql for update语法实现行锁:http://blog.techbeta.me/2014/11/mysql-for-update/

上一篇下一篇

猜你喜欢

热点阅读