mysql--读写锁
一.简介
假设现在有这样一个场景:假设现在有一个邮箱,在同一时刻无论是单个还是多个用户并发的去读取某一封邮件,都没有问题。因为读取邮件并不会修改数据,所以不会出错;
但是某个用户正在读取某一封邮件时,同时另一个用户正在删除这封邮件,那么读取邮件的用户可能会因为找不到而退出。
解决此类问题的方法就是并发控制,在并发读或者写时,可以通过读锁(read lock)或写锁(write lock)来解决问题,读锁和写锁也被成为共享锁(shared lock)和排它锁(exclusive lock)。
读锁:读锁是共享的,或者说是互不干涉的。多个客户端在同一时刻可以同时读取一个资源,而互不干扰。
写锁:写锁则是排他的,也就是说一个写锁会阻塞其他的写锁和读锁,只有这样才能保证在给定的时间里,只有一个用户能执行写入,并防止其他用户读取正在写入的同一资源。
二.演示
读锁:
事务一 | 事务二 |
mysql> set autocommit=0; #事务不主动提交 |
mysql> set autocommit=0; |
#查询id为1的用户信息并加上共享锁 mysql> select * from user where id = 1 lock in share mode; |
|
#其他事务也能查询id=1的用户 mysql> select * from user; |
|
#对id=1的用户进行修改 mysql> update user set name='ludy' where id=1; 正在等待中... |
|
#此时提交事务 mysql> commit; |
|
#修改成功 mysql> update user set name='ludy' where id=1; |
写锁:
事务一 | 事务二 | 事务三 |
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=1的用户信息 mysql> select * from user where id=1 for update; 等待中... |
||
#其他事务对id=1进行修改 mysql> update user set name='timi' where id = 1; 等待中... |
||
#提交事务 释放锁 mysql> commit; |
||
#查询成功 | #修改成功 |
for update是有超时时间的,当一个事务等待时间超过设置的超时时间时,将会获得锁。
超时时间可通过show global VARIABLES like "%timeout%";命令查看,innodb_lock_wait_timeout就是。
三.总结
读写锁的本质都是行级锁,而在Mysql中只有Innodb支持行级锁。
Innodb将通过检索条件中的索引来加锁,如果没有检索条件则对所有记录加锁,即表锁。
本文来自博客园,作者:EchoLv,转载请注明原文链接:https://www.cnblogs.com/lvdeyinBlog/p/15231416.html