mysql--读写锁

一.简介

假设现在有这样一个场景:假设现在有一个邮箱,在同一时刻无论是单个还是多个用户并发的去读取某一封邮件,都没有问题。因为读取邮件并不会修改数据,所以不会出错;

但是某个用户正在读取某一封邮件时,同时另一个用户正在删除这封邮件,那么读取邮件的用户可能会因为找不到而退出。

解决此类问题的方法就是并发控制,在并发读或者写时,可以通过读锁(read lock)写锁(write lock)来解决问题,读锁和写锁也被成为共享锁(shared lock)排它锁(exclusive lock)。

读锁:读锁是共享的,或者说是互不干涉的。多个客户端在同一时刻可以同时读取一个资源,而互不干扰。

写锁:写锁则是排他的,也就是说一个写锁会阻塞其他的写锁和读锁,只有这样才能保证在给定的时间里,只有一个用户能执行写入,并防止其他用户读取正在写入的同一资源。

二.演示

读锁:

事务一 事务二

mysql> set autocommit=0; #事务不主动提交
Query OK, 0 rows affected (0.00 sec)

mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

#查询id为1的用户信息并加上共享锁

mysql> select * from user where id = 1  lock in share mode;
+----+----------+------+------+--------------------+
| id | password | name | age | email |
+----+----------+------+------+--------------------+
| 1 | NULL | lv | 18 | test1@baomidou.com |
+----+----------+------+------+--------------------+
1 row in set (0.00 sec)

 
 

#其他事务也能查询id=1的用户

mysql> select * from user;
+----+----------+--------+------+--------------------+
| id | password | name | age | email |
+----+----------+--------+------+--------------------+
| 1 | NULL | lv | 18 | test1@baomidou.com |
| 2 | NULL | Jack | 20 | test2@baomidou.com |
| 3 | NULL | Tom | 28 | test3@baomidou.com |
| 4 | NULL | Sandy | 21 | test4@baomidou.com |
| 5 | NULL | Billie | 24 | test5@baomidou.com |
+----+----------+--------+------+--------------------+
5 rows in set (0.00 sec)

 

#对id=1的用户进行修改

mysql> update user set name='ludy' where id=1;

正在等待中...

#此时提交事务

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

 
 

#修改成功

mysql> update user set name='ludy' where id=1;
Query OK, 1 row affected (46.30 sec)
Rows matched: 1 Changed: 1 Warnings: 0


写锁:

事务一 事务二 事务三
mysql> set autocommit=0; #事务不主动提交
Query OK, 0 rows affected (0.00 sec)
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

#将id=1的用户加入排它锁

mysql> select * from user where id=1 for update;
+----+----------+------+------+--------------------+
| id | password | name | age | email |
+----+----------+------+------+--------------------+
| 1 | NULL | ludy | 18 | test1@baomidou.com |
+----+----------+------+------+--------------------+
1 row in set (0.00 sec)

   
 

 #此时其他事务访问id=1的用户信息

mysql> select * from user where id=1 for update;

等待中...

 
   

#其他事务对id=1进行修改

mysql> update user set name='timi' where id = 1;

等待中...

#提交事务 释放锁

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

   
   #查询成功  #修改成功

for update是有超时时间的,当一个事务等待时间超过设置的超时时间时,将会获得锁。

超时时间可通过show global VARIABLES like "%timeout%";命令查看,innodb_lock_wait_timeout就是。

三.总结

读写锁的本质都是行级锁,而在Mysql中只有Innodb支持行级锁。

Innodb将通过检索条件中的索引来加锁,如果没有检索条件则对所有记录加锁,即表锁。

 

posted @ 2021-09-05 22:05  EchoLv  阅读(712)  评论(0编辑  收藏  举报