Mysql中的锁

Posted SSimeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql中的锁相关的知识,希望对你有一定的参考价值。

mysql中锁的介绍

1. Mysql引擎

MySQL引擎就是指表的类型。数据库的存储引擎决定了表在计算机中的存储方式。
分类:通过show engines;查看。结果如下图所示、

创建新表时如果不指定存储引擎,那么系统就会使用默认的存储引擎,MySQL5.5之前的默认存储引擎是MyISAM,5.5之后就改为了InnoDB。
查看数据库的引擎命令:
对比:

show variables like '%storage_engine%' 

2. 锁的定义

概念:锁是计算机协调多个进程或线程并发访问某一资源的机制。锁可以保证数据并发访问的一致性有效性;锁是Mysql在服务器层存储引擎层的的并发控制。
注意:加锁是消耗资源的,锁的各种操作,包括获得锁、检测锁是否是否已解除、释放锁等.

3. 锁的分类

(1)按锁的粒度分类

根据锁的粒度划分,可以将锁分为行级锁页级锁表级锁

行级锁:是MySQL锁定粒度最小的一种锁,表示只针对当前操作的进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,单加锁开销最大。InnoDb支持行级锁。
页级锁:是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。
表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MYISAM与INNODB都支持表级锁定。

对比:表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。BDB支持页级锁

(2)按锁的级别分类

根据锁的级别划分,可以将锁分为共享锁排它锁


共享锁:又称"读锁",是读取操作创建的锁。其他用户可以并发读取数据,但任何事务都不能对数据进行修改(获取数据上的排他锁),直到已释放所有共享锁。

SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE;  --加共享锁 

排它锁:又称"写锁",如果事务T对数据A加上排他锁后,则其他事务不能再对A加任任何类型的封锁。获准排他锁的事务既能读数据,又能修改数据。

SELECT * FROM table_name WHERE ... FOR UPDATE;--加排它锁 

(3)按加锁的方式分类

按加锁的方式,可以分为自动锁显示锁
Tips: INSERT、UPDATE、DELETE InnoDB会自动加排他锁,对于普通SELECT语句,InnoDB不会加任何锁

(4)按操作进行分类

按操作进行分类,可分为DML锁,DDL锁

DML(data manipulation language):数据操作语言。
它们是SELECT、UPDATE、INSERT、DELETE,这4条命令是用来对数据库里的数据进行操作的语言,这些语句的操作对于的锁为DML锁

DDL(data definition language):数据定义语言
DDL比DML要多,主要的命令有CREATE、ALTER、DROP等,DDL主要是用在定义或改变表的结构,数据类型,表之间的连接和约束等初始化工作上,他们大多在建立表时使用。这些语句的操作对于的锁为DDL锁

(5) 按适用方式分类

按适用方式分类:悲观锁和乐观锁

悲观锁(Pessimistic Concurrency Control,PCC):假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。

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

优缺点:
① 悲观的缺陷是不论是页锁还是行锁,加锁的时间可能会很长,这样可能会长时间的限制其他用户的访问,也就是说悲观锁的并发性不好。但这也保证了数据的安全性
② 乐观锁不能解决脏读,加锁的时间要比悲观锁短(乐观锁可以获得较好的并发访问性能。但是不能保证安全性。比如:如果第二个用户恰好在第一个用户提交更改之前读取了该对象,那么当他完成了自己的更改进行提交时,数据库就会发现该对象已经变化了,这样,第二个用户不得不重新读取该对象并作出更改。

4. 死锁的原理及分析

(1) MVCC

​MySQL InnoDB存储引擎,实现的是基于多版本并发控制协议—MVCC(Multi-Version Concurrency Control) 。
MVCC最大的好处,读不加锁,读写不冲突。在读多写少的应用中,读写不冲突是非常重要的,极大的增加了系统的并发性能,这也是为什么现阶段,几乎所有的RDBMS,都支持了MVCC。

(2)两段锁:2PL

​ 传统RDBMS加锁的一个原则,就是2PL (二阶段锁):Two-Phase Locking。锁操作分为两个阶段:加锁阶段与解锁阶段,并且保证加锁阶段与解锁阶段不相交。
过程:

(3)为什么会发生死锁

MyISAM中是不会产生死锁的,因为MyISAM总是一次性获得所需的全部锁,要么全部满足,要么全部等待。而在InnoDB中,锁是逐步获得的,就造成了死锁的可能。
在InnoDB中,行级锁并不是直接锁记录,而是锁索引。索引分为主键索引和非主键索引两种,如果一条sql语句操作了主键索引,MySQL就会锁定这条主键索引;如果一条语句操作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引。
当两个事务同时执行,一个锁住了主键索引,在等待其他相关索引。另一个锁定了非主键索引,在等待主键索引。这样就会发生死锁。

(4)如何避免死锁

(1)如果不同程序会并发存取多个表,尽量约定以相同的顺序访问表,可以大大降低死锁机会。
(2)在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率;
(3)对于非常容易产生死锁的业务部分,可以尝试使用升级锁定颗粒度,通过表级锁定来减少死锁产生的概率;

以上是关于Mysql中的锁的主要内容,如果未能解决你的问题,请参考以下文章

Mysql中的锁

MySQL innoDB 中的锁升级

MySQL中的锁

mysql中的锁机制之悲观锁和乐观锁

说一说MySQL的锁机制

MySQL——innodb锁