文章目录

  • 一、并发控制定义
  • 二、读写锁
  • 1.概念
  • 2.类型
  • 三、锁粒度
  • 1.概念
  • 2.级别
  • 三、语句实现部分
  • 搭建实验环境
  • 1.表锁实现写锁
  • 2.表锁实现读锁


一、并发控制定义

多个查询需要在同一时刻修改数据就会产生并发控制的问题,两个主机互相通信实质是依靠进程之间进行通信的,但是如果两个进程同一时刻对一个邮箱投递邮件,当然邮箱会崩溃掉,两封邮件的内容会交叉的附加在邮箱文件的末尾。设置良好的邮箱投递系统当然会通过(lock)锁来防止数据发生损坏。比如当一个用户正在投递时,另一个就无法进行投递只能等待上一个用户投递完成后才可以进行投递。
这种锁的解决方案虽然很有效的保证了数据的完整性但是却不支持并发处理,只可以单独进程进行访问,这当然会在大容量的邮箱系统中产生并发数不够的问题,从而造成用户流失。

二、读写锁

1.概念

比如在数据库中Tom正在修改数据库的a表,但同时Alex想要读取这个表,或者Alex正在读取这个表而Tom想要删除这个表,那么访问的用户会出错或者删除不成功,等一系列问题。如果想要解决这种问题的方法就是并发控制,在处理并发读或者写时,可以通过两种类型的锁来解决问题。读锁(read lock)和写锁(write lock)。

2.类型

读锁(read lock): 读锁是共享的,可以多人一起读取一个资源而且互不干扰。
写锁(write lock): 是排他的,只许单独用户访问,不许多人同时读也就是说一个写锁会阻塞其他的写锁和读锁。
优先级:写锁的优先级更大一些,当写锁可以插入到读锁前面,而读锁不能插入到写锁前面。

三、锁粒度

1.概念

锁粒度就是锁的级别,如果只锁定修改的部分而不是所有的资源那么耗费的资源就会比较少,因为加锁也会耗费资源,锁定的数据量越少,则系统的并发程度就会越高。锁策略就是在锁的开销和数据的安全性之间寻求平衡。
一般都是在表上施加行锁(level lock)但是MySQL会在存储引擎层将锁粒度固定在某个级别。
优点:可以为某些特定的应用场景提供很好的性能
缺点:会失去两外一些应用场景的良好支持

2.级别

1.页级(page lock): 对相邻的数据进行锁定,介于表锁与行锁之间,DBD引擎支持,支持的并发量一般
2.表级(table lock): 是开销最小的策略,当一个用户在对表进行修改、删除、更新数据时,会先获得写锁从而阻塞其他用户对该表的写操作。可以直接在服务器使用语句使用表锁,从而忽略存储引擎的锁机制。
3.行级(row lock): 是开销最大的策略,最大程度支持了并发处理,而这种行锁只能在存储引擎层按照存储引擎的机制进行实现,不可以通过服务器语句来进行实现。

三、语句实现部分

搭建实验环境

1)两个终端:A端与B端同时连接同一个MySQL数据库
2)创建数据库test与biao1,并添加数据

mysql> create database test;
mysql> use test;
mysql> create table biao1(id int, name char(10));
mysql> insert into biao1(id, name) values(1,'成龙');
mysql> select * from biao1;
+------+------+
| id   | name |
+------+------+
|    1 | 成龙 |
+------+------+
1 row in set (0.00 sec)

1.表锁实现写锁

A端:实现表锁中写锁

mysql> lock table biao1 write;

B端:select查看biao1,但是一直是处于等待状态

mysql> select * from biao1;
^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted

B端:insert插入数据到biao1,但是也处于等待状态

mysql> insert into biao1(id,name) values(2,'吴亦凡');
^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted

A端:既然B端无法查看和插入数据,那么看一下A端

mysql> insert into biao1(id,name) values(2,'吴亦凡');
mysql> select * from biao1;
+------+--------+
| id   | name   |
+------+--------+
|    1 | 成龙   |
|    2 | 吴亦凡 |
+------+--------+
2 rows in set (0.00 sec)

结论: 在A端对biao1使用写锁后,B端无法查看以及插入数据,但是A端可以。

2.表锁实现读锁

A端:释放上次的写锁,并添加读锁

mysql> unlock tables;
#释放
mysql> lock table biao1 read;
#添加

B端:select查看biao1,可以查看

mysql> select * from biao1;
+------+--------+
| id   | name   |
+------+--------+
|    1 | 成龙   |
|    2 | 吴亦凡 |
+------+--------+
2 rows in set (0.00 sec)

B端:insert插入数据到biao1,超时无法插入

mysql> insert into biao1(id,name) values(3,'吴京');
^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted

A端:使用读锁后,在A端也无法插入数据了,只允许查看数据

mysql> insert into biao1(id,name) values(3,'吴京');
ERROR 1099 (HY000): Table 'biao1' was locked with a READ lock and can't be updated

结论: 在使用读锁后,所有用户都只可以读取数据,但是不能插入数据,因为读锁是共享的,所以可以多人同时查看。