锁的分类:
对数据库操作的粒度分:行锁,表锁
对数据操作的类型分:读锁,写锁
读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响;
写锁(排它锁):当前写操作没有完成前,它会阻断其他写锁和读锁;
三种锁:
表锁(偏读):
偏向MyISAM引擎,开销小,加锁快;无死锁;锁定力度大,发生锁冲突的概率最高,并发度最低
我们测试一下MyISAM引擎的锁
建立一张表 指定使用myisam引擎
代码语言:javascript复制create table mylock (
id int not null primary key auto_increment,
name varchar(20) default ''
) engine myisam;
insert into mylock(name) values('a');
insert into mylock(name) values('b');
insert into mylock(name) values('c');
insert into mylock(name) values('d');
insert into mylock(name) values('e');
测试锁 我们需要打开两个连接测试 我们命名为session1 session2
测试上锁:
查看表上的锁
代码语言:javascript复制show open tables;
现在还没有锁
给mylock表上读锁 book上写锁
代码语言:javascript复制lock table mylock read,book write;
我们在查看表上的锁
代码语言:javascript复制show open tables;
这两个表有了锁
解锁操作
代码语言:javascript复制unlock tables;
show open tables;
上锁操作测试完了 我们来测试一下读锁会有哪些锁定限制
加上读锁
代码语言:javascript复制lock table mylock read;
两个连接进行查询 都可以查询的到
这时我们使用session1(也就是对表加读锁的那个连接)进行数据修改
可以看到报错了
代码语言:javascript复制 Table 'mylock' was locked with a READ lock and can't be updated */
表已经被锁定无法更新
那这个是后这时候我们这个session1连接能访问其他的表么
我们用锁定表的session1连接测试读取其他表
代码语言:javascript复制select * from book;
结论是不能
我们再用session2连接 测试读取其他表
我们可以看到是可以的
那seession2连接可以修改当前表么
我们可以看到 会一直阻塞 知道session把表的锁释放才执行
代码语言:javascript复制结论:被读锁锁定期间 锁定表的线程可以读取锁定的表 修改锁定的表不可以 读取别的表也不可以
其他线程:可以读取锁定的表,可以读取其他线程 ,修改锁定的表会一直阻塞到session1表的读锁释放才执行
读锁测试完了 我们在测试一下写锁
把当前所有的锁释放
代码语言:javascript复制unlock tables;
mylock表加上写锁
代码语言:javascript复制lock tables mylock write;
session1连接测试修改自己
代码语言:javascript复制update mylock set name='a1' where id=1;
修改成功
session2测试修改
代码语言:javascript复制update mylock set name='a11' where id=1;
又阻塞了
这时我们session1释放写锁
session2写成功
我们session1再加锁进行测试
代码语言:javascript复制lock tables mylock write;
session1读取其他表 还是无法读取 锁没有释放
session2读取其他表
代码语言:javascript复制select * from book;
成功
session2查询mylock表
会一直阻塞到session1释放锁
代码语言:javascript复制结论:session1可以对锁定的表进行增删改查 session2对当前的表进行操作会一直阻塞到锁释放
MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行增删改操作前,会自动给涉及的所有表加写锁 总结: 1.对MyISAM表的读操作,不会阻塞其它进程对同一表的读请求,但会阻塞对同一表的锁请求,只有当锁释放了后才会执行其他线程的写操作。 2.对MyISAM表的写操作,会阻塞其它进程对同一张表的读和写操作,只有当锁释放了之后,才会执行其他进程的读写操作。