准备测试数据
1.建立两个表,分别为S和T,插入一些数据
-- 创建表S
create table s(
d int
) ENGINE=innodb DEFAULT CHARSET=utf8;
INSERT INTO s(d) VALUES (1);
-- 创建表T
create table t(
c int
) ENGINE=innodb DEFAULT CHARSET=utf8;
insert into t values (10);
2.打开两个客户端连接
读锁
1.对锁定表进行查看、修改
在session1中对t表加read锁,查看此时session1和session2对t表的读写情况。
窗口1
窗口2
结果:一个session(多个事务)中对某张表加上读锁,该表的数据可读不可写。另一个session(多个事务)中,该表的数据也是可读不可写。但是表现略有不同,加锁会话中返回错误提示,不加锁会话中处于阻塞。session1执行"unlock tables"解锁操作,或者session1关闭,session2都会立刻解除阻塞状态。
2.对非锁定表进行查看、修改
在session1中对t表加read锁,查看此时session1和session2对s表的读写情况。
窗口1
结果:一个session中对某张表加上读锁,锁定表可以查询但不可以修改,非锁定表不能查询且不能修改。另一个session中锁定表可以查询但不可以修改,非锁定表可以查询且可以修改。
至此,不禁产生了一个疑问。为什么当前加锁会话锁了A表,却不能操作其它非锁定表?为什么另一个会话就可以操作非锁定表?
一开始是懵逼的,之后想了想,其实可以这么理解。我们回想一下共享锁的定义,共享锁就是多个事务对于同一数据可以共享一把锁。也就是说,这一把锁可以在多个session中的事务中实现共享、共用,所以可以很清楚的看到,读锁在多个事务中产生了同样的作用,即都只能读数据不能修改数据。另外,加锁会话中对A表加共享锁,意思就是加了一把可以共享使用的锁,且该锁只针对A表,只让你拥有针对于A表的读权限。因此,不论是在当前会话的事务中还是其它会话的事务中,我们都只能读A表而不能修改A表。最后,在另一个非加锁会话中,我们可以查询并修改非锁定表,这是因为共享的锁,对于加锁的自身会话,意味着只有A表的读权限;对于其他会话,意味着A表只有读权限,其他表有读写权限。
下面基于上述的基础上再测试一下
结果:一个会话中加了A表的读锁,另一个会话可以继续加A表的读锁,并且另一个会话中无法查询和修改非锁定表了。这说明,共享的锁,对于加锁的自身会话,意味着只有A表的读权限;对于其他会话,意味着A表只有读权限,其他表有读写权限。
不同会话中的表现
Ps: 默认情况下,MySQL用户执行的每一条SQL语句都会被当成单独的事务自动提交。
3. 在两个会话中对同一个表加read锁
show open tables where in_use:表示有多少线程正在使用某张表
结果: 通过执行“show open tables where in_use > 0”,可以看到,当前t表被两个线程锁住了,In_use=2。
最后小结
共享锁,对于加锁的会话,意味着只有该表的读权限;对于其他会话,意味着该表只有读权限,其他表有读写权限。
简言之,共享锁,对于加锁的会话,只可以读锁定表;对于其他会话,还可以读写非锁定表。