【MySQL】mysql中的锁机制

一、分类

MySQL的锁机制不同的存储引擎支持不同的锁机制,分为表级锁、行级锁、页面锁。MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking);BDB存储引擎采用的是页面锁(page-level locking),但也支持表级锁;InnoDB存储引擎既支持行级锁(row-level locking),也支持表级锁,但默认情况下是采用行级锁

 

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

二、表级锁

MySQL的表级锁有两种模式:表共享读锁(Table Read Lock)表独占写锁(Table Write Lock)。 

对MyISAM表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;对 MyISAM表的写操作,则会阻塞其他用户对同一表的读和写操作。

MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作 (UPDATE、DELETE、INSERT等)前,会自动给涉及的表加写锁,这个过程并不需要用户干预,因此,用户一般不需要直接用LOCK TABLE命令给MyISAM表显式加锁。

三、行级锁

InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION);二是采用了行级锁。

行级锁也支持读锁和写锁两类。

1、如何加锁?

mysql InnoDB引擎默认的修改数据语句:update,delete,insert都会自动给涉及到的数据加上排他锁,select语句默认不会加任何锁类型,如果加排他锁可以使用select …for update语句,加共享锁可以使用select … lock in share mode语句。所以加过排他锁的数据行在其他事务种是不能修改数据的,也不能通过for update和lock in share mode锁的方式查询数据,但可以直接通过select …from…查询数据,因为普通查询没有任何锁机制。

 2、实现原理

InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,并请求共享或排他锁时,InnoDB才使用行级锁,否则,InnoDB将使用表锁! 

、锁的算法

  • record lock:单个记录的锁。
  • gap lock:间隙锁,锁定一个范围,不包括记录本身
  • next-key lock:gap lock+record lock

默认隔离级别(可重复读)下,默认加的是next-key lock(为了解决幻读问题),当索引中含有唯一属性时(唯一索引,主键索引),会降级为record lock。

在读已提交隔离级别下,加的是record lock

1、例1

现在表z,有a,b两列,a是主键,全表只有一个主键索引。现在记录如下:(1,1)(3,1)(5,3)(7,6)(10,8)

select * from z where b=3 for update

因为b没有索引,所以走得是全表扫描。有因为加锁是通过对索引加锁实现,因为没有走索引,所有会锁整个表,也就是表锁

 2、例2

现在表z,有a,b两列,a是主键索引,b建立辅助索引。现在记录如下:(1,1)(3,1)(5,3)(7,6)(10,8)

select * from z where a=3 for update

主键索引加的锁是record lock,对记录(3,1)加锁

select * from z where b=3 for update

因为锁是通过对索引加锁实现的。所以这里需要对主键索引和辅助索引加锁,主键索引加的锁会由next-key锁退化成是record lock,辅助索引加的锁是next-key lock,锁定范围是(1,3)、3、(3,6)

五、select的几种类型

1、快照读

读取的是快照版本,也就是历史版本。普通的SELECT就是快照读

2、当前读

读取的是最新版本。

UPDATE、DELETE、INSERT、SELECT ...  LOCK IN SHARE MODE、SELECT ... FOR UPDATE是当前读。

默认的可重复读隔离级别,使用的是快照读

读已提交使用的是当前读

3、一致性非锁定读

实现原理是通过MVCC机制实现,如果读取的行正处于update或delete中,读操作不会去等待行上X锁的释放,而是去读取行的快照数据。

MVCC,多版本并发控制技术。在 InnoDB 中,在每一行记录的后面增加两个隐藏列,记录创建版本号和删除版本号。通过版本号和行锁,从而提高数据库系统并发性能。

一致性非锁定读可以极大的提高并发性能

不同的事务隔离级别,读取的快照版本是有差别的

  • 读已提交隔离级别,总是读取最新的快照版本。可能会产生幻读
  • 可重复读隔离级别,总是读取事务开始后第一次读取的快照版本。可以避免幻读的产生

4、一致性锁定读

默认配置下,采用可重复读的隔离级别,读取数据采取的是一致性非锁定读。

但是某些场景下需要对读取操作加锁来保证严格的数据一致性,这时候可以显式的对读取的记录进行加锁:

  • select *** for update(对读取记录加X锁)
  • 给索引记录加锁,这种情况下跟UPDATE的加锁情况是一样的
  • select *** lock in share model(对读取记录加S锁)  
  • 给记录假设共享锁,这样一来的话,其它事务只能读不能修改,直到当前事务提交

 

posted @ 2019-07-19 19:44  leon66666  阅读(233)  评论(0编辑  收藏