深入了解Mysql中的锁,聊聊使用场景!

文 / @WordPress主题

深入了解Mysql中的锁,聊聊使用场景!

Mysql是一个非常流行的关系型数据库管理系统,被广泛使用在各种Web应用中。在使用Mysql时,锁是一个非常重要的概念,对于理解Mysql的并发控制和性能调优都有很大的帮助。本文将围绕常见的锁类型、Mysql引擎介绍、共享锁与排他锁、死锁的发生和解决方式、意向锁和计划锁以及乐观锁和悲观锁展开讨论。

一、常见锁类型

Mysql中常见的锁类型包括:

1.表级锁 - 锁定整张表

2.页级锁 - 锁定一页

3.行级锁 - 锁定一行

4.共享锁 - 又称为S锁,在MyISAM中也叫做读锁

5.排他锁 - 又称为X锁,在MyISAM中也叫做写锁

6.悲观锁 - 抽象性质,其实并不存在

7.乐观锁 - 抽象性质,其实并不存在

其中,行级锁是Mysql的默认锁类型,也是最常用的锁类型,提高了系统并发度和性能,减少了锁冲突。

二、Mysql引擎介绍

Mysql中常用的引擎有很多种类,其中InnoDB和MyISAM引擎最为常用。在Mysql5.5版本之前,默认使用MyISAM引擎,之后默认都使用InnoDB引擎。可以通过以下命令查看数据库引擎:

show variables like '%storage_engine%';

MyISAM引擎操作数据时使用的是表级锁,更新一条记录就需要锁定整个表,导致性能较低,并发性也不高。然而,MyISAM的优点是不会产生死锁问题。相比之下,InnoDB引擎有以下两个最大不同点:一是支持事务,二是采用了行级锁。

三、共享锁与排他锁

在Mysql中,数据库的增删改操作默认会加上排他锁,而查询操作不会加任何锁。常见的锁类型包括共享锁和排他锁,区别如下:

共享锁 - 对某一资源加上共享锁,自身可以读该资源,其他人也可以读该资源。共享锁可同时加多个,但无法修改资源。

排他锁 - 对某一资源加上排他锁,自身可以进行增删改查,其他人无法进行任何操作。

可以通过以下代码实现对表进行共享锁和排他锁的操作:

//共享锁
select * from table_name lock in share mode;

//排他锁
select * from table_name for update;

四、排他锁的实际应用

以下示例展示了两个操作数据库的请求T1和T2,其中T1是查询请求,而T2是更新数据请求。在T1查询较长时间的过程中,T2过来请求更新数据。为了避免冲突,T2必须等待T1完成后,才能继续执行。

T1: select * from table_name lock in share mode; //假设还未返回结果

T2: update table_name set name = 'autofelix';

五、共享锁的实际应用

如果T1和T2都是执行的查询操作,则可以采用共享锁的方式,避免等待。共享锁可以与其他共享锁共存,但是阻止其他用户的修改操作,具体代码如下:

T1: select * from table lock in share mode;

T2: select * from table lock in share mode;

六、死锁的发生

死锁是指两个或多个进程,在运行过程中因争夺资源而造成的相互等待的现象。以下是一种发生死锁的情况:

假设T1和T2都执行了两个资源的操作,其中T1查询并加上了共享锁,T2也加上了共享锁。当T1的查询完成后,准备执行更新操作时,必须将共享锁升级为排他锁。在升级前,必须等待T2的共享锁释放。同样地,T2也在等待T1的共享锁释放。由于互相等待,导致了死锁的发生。

T1: begin; select * from table_name lock in share mode; update table_name set content = 'hello' where id = 10;

T2: begin; select * from table_name lock in share mode; update table_name set content = 'world' where id = 20;

七、另一种发生死锁的情景

当T1和T2都只执行更新语句时,也有可能出现死锁的情况。如果id是主键,由于主键机制,并不需要全表扫描,可以直接更新当前数据,所以不会产生死锁。但如果id是普通字段,那么当T1加上排他锁后,T2为了找到id=20的数据,必须进行全表扫描。当扫描到第10条时,

添加UTHEME为好友
扫码添加UTHEME微信为好友
· 分享WordPress相关技术文章,主题上新与优惠动态早知道。
· 微信端最大WordPress社群,限时免费入群。