锁:计算机协调多个进程或线程并发访问某一资源的机制。
在数据库中,除传统的计算资源(如CPU、RAM、I/O等)的争用外,数据也是一种供许多用户共享的资源。如何保证数据并发的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而言显得尤为重要,也更复杂。
1)从对数据操作的类型分为读锁和写锁
2)从对数据操作的粒度分主要有表锁和行锁
读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响。
写锁(排他锁):当前写操作没有完成前,它会阻断其他读和写操作。
先看一些命令
我们可以手动对一张表加锁,可以是读锁或者写锁,命令:
lock table 表名 read/write,表名 read/write,……
查看表有没有锁的命令
show open tables;
In_use的值是0代表没锁,是1代表有锁。
现在数据库中有一张表,test_lock,现在手动给它加锁,进行一些操作测试。
一、加读锁
lock table test_lock read;
加锁成功,可以用show open tables命令查看
现在可以做一些操作。
1、读被锁的表:
select * from test_lock;
在当前连接中:
可以查询到结果。
在新连接中:
新的连接同样可以查询被锁的表。
2、查询库中其他表:
select * from test2;
在当前连接中:
结果报错,无法查询。
在新连接中:
正常,没有影响。
3、更新被锁的表:
update test_lock set name = 'abcd' where id = '1';
在当前连接中:
无法更新。
在新连接中:
执行此语句后,会发现一直在等待,即阻塞了,直到我们把表的锁释放。
释放锁命令:unlock table;
执行释放命令后,新连接中的update语句也马上有了反应,
执行等待了1分多钟。
4、更新库中其他表:
update test2 set name = 'a2' where id = '1';
在当前连接中:
无法更新
在新连接中:
在新的会话中,更新其他表是没有影响的。
二、加写锁
lock table test_lock write;
同样,我们在当前会话和和新会话中做一些操作对比。
1、读被锁的表:
select * from test_lock;
当前会话中:
读没有影响。
新的会话中:
此时会被阻塞,需要等待释放锁。
2、查询库中其他表:
select * from test2;
当前会话中:
其他表不能查询。
新的会话中:
此时不受影响。
3、更新被锁的表:
update test_lock set name = 'abcd' where id = '2';
当前会话中:
可以更新。
新的会话中:
结果是被阻塞。
4、更新库中其他表
update test2 set name = 'a2' where id = '2';
当前会话中:
此时不可以更新其他表。
新的会话中:
更新其他表时候没有问题。
以上是对表分别加读锁和写锁,然后进行的一些操作对比,重要的关注在其他会话中对被锁表的读写请求。
对表加读锁,不会阻塞其他进行对同一表的读请求,但会阻塞对同一表的写请求。只有当读锁释放后,才会执行其他执行进行的写操作。
对表加写锁,会阻塞其他进程对同一表的读和写的请求,只有当写锁释放后,才会执行其它进程的读写操作。