前言
数据库为什么需要锁呢?这是为了防止多人操作同一数据时,破会数据一致性的情况。举个例子:(正在吃饭的请吃完饭在读)厕所的坑是有数的,当大家需要排泄的时候便需要去蹲坑(假设厕所是一个小单间,有隔板、有锁),在有坑的时候(也就是资源),大家便会上去占用资源。那么没有呢,便会等待。等待锁打开的时候,你才能进去占用茅坑。
类型
这里锁的类型,博主这里会从多个角度分析,希望大家能够喜欢,有错误的地方请在下方评论指出,博主会及时修正。由于MySQL数据库的锁机制是根据存储引擎不同而不同,这里博主根据不同引擎引入不同类型的锁机制。
MyISAM引擎
MyISAM引擎是MySQL数据库的默认存储引擎,但是在5.7版本后需要在表后声明使用MyISAM引擎,才能使用该引擎(具体是从哪个版本开始,博主不是很清楚,博主使用的是MySQL5.7版本便是这种情况,所以博主便指定这个版本,大家知道的话可以跟博主说一下,谢谢大家)。
表锁
表锁是MyISAM引擎支持的唯一锁机制,那么什么是表锁?表锁有什么用呢?
- 表锁解释
表锁机制就是每次锁定一张表的机制。表锁机制粒度最大(粒度可以理解为范围),也是最容易出现锁冲突现象(锁冲突现象:将资源看做一个库房,一个仓库管理员A打开门进入并从里边上锁,外边不可打开。仓库管理员B只能排队等待仓库管理员A用完资源,并在外边上锁,才能进入仓库)。 - 优缺点
优点:开销小、不会出现死锁问题。
缺点:出现锁冲突概率很大。
表级锁类型
- 表共享读锁
不会阻塞其他用户对表的读操作,但会阻塞写的请求。 - 表独占写锁(串行执行)
阻塞其他用户对表的任何读写请求。
测试
- 添加只读锁
LOCK table student READ;
添加只读锁后不允许用户进行写操作(包含insert、updata、delete)。测试如下:
INSERT INTO student VALUES ('35469','gh','Biology',6);
查看写数据进程:
SHOW PROCESSLIST;
消除锁
UNLOCK TABLES;
重新插入数据:
INSERT INTO student VALUES ('35469','gh','Biology',6);
- 添加写锁
LOCK TABLE student WRITE;
添加写锁后,不允许用户进行写和读操作。测试如下:
SELECT * FROM student;
查看读数据进程:
SHOW PROCESSLIST;
消除锁
UNLOCK TABLES;
FLUSH PRIVILEGES;
读取数据
SELECT * FROM student;
InnoDB引擎
InnoDB引擎既支持表锁又支持行锁。行锁顾名思义便是给数据记录添加行锁机制(数据记录是指对应于数据源中一行信息的一组完整的相关信息。)。但InnoDB引擎不是对数据记录加锁而是对数据记录的索引项加锁。
行锁
InnoDB引擎是对数据记录的索引项加锁。行锁都是基于索引的,若没有索引则会转换成表锁。
行锁类型
排它锁(写锁)
排它锁又称为写锁((eXclusive lock,简记为X锁)),若事务T对数据对象A加上X锁,则只允许T读取和修改A,其它任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。它防止任何其它事务获取资源上的锁,直到在事务的末尾将资源上的原始锁释放为止。
博主的理解:假设目前只有一本《MySQL数据库概念》书,博主和各位都想去“读写”,如果博主先占用了该资源,并盖上博主的标签(锁)。那么大家就不能再添加任何标签(锁),但可以读取。
InnoDB引擎默认的修改数据语句,update、delete、insert都会自动给涉及到的数据加上排他锁,select语句默认不会加任何锁类型。若加排他锁,则可以使用select …for update语句。
测试数据:
- 利用select…for update进行加排它锁查询(这里student.ID为主键也相当于索引)
BEGIN;
SELECT * FROM student WHERE student.ID='00128' FOR UPDATE;
-- COMMIT
- 测试添加其他排它锁
SELECT * FROM student WHERE student.ID='00128' FOR UPDATE;
- 不添加排它锁查询
SELECT * FROM student WHERE student.ID='00128';
共享锁(读锁)
共享锁(S锁)又称为读锁,若事务T对数据对象A加上S锁,则事务T只能读A;其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这就保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。
博主理解:所谓共享锁就是博主加了一把S锁,其他用户也可加S锁但不能加X锁。举个例子:假设博主拥有了一个楼盘用于出租,楼盘每层都有卫生间,卫生间有一面镜子,每层卫生间的厕所都是公用的,每个商户都可以去用这面镜子,但不能在这面镜子上乱写乱花画。也就是说,如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。对于select操作,InnoDB不会对数据加任何锁,如果需要,事务可以给select操作显式的加共享锁使用select…lock in share mode。
测试数据:
- 利用select … lock in share mode添加共享锁
BEGIN;
SELECT * FROM student WHERE student.ID='00128' lock in share mode;
-- COMMIT;
- 测试其他用户是否可以使用共享锁或者排它锁
select user();
SELECT * FROM student WHERE student.ID='00128' lock in share mode;
SELECT * FROM student WHERE student.ID='00128' for update;
- 去除锁
UNLOCK TABLES;
总结
以上是博主初步的一个学习总结,哪里有问题请及时指出,大家一起进步。