锁是计算机协调多个进程或线程并发访问某一资源的机制
在数据库中,数据也是一种供许多用户共享的资源。如何保证数据并发访问得一致性,有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素
锁对数据库而言显得尤其重要,也更加复杂
MyISAM 采用 表级锁
InnoDB 支持行级锁 也支持表级锁 默认情况采用行级锁
表级锁 开销小,加锁快 不会出现死锁 锁定粒度大 发生锁冲突的概率最高 并发度最低
行级锁 开销大 加锁慢 会出现死锁 锁定粒度最小, 发生锁冲突的概率最低 并发度也最高
页面锁 开锁和加锁时间界于表锁和行锁之间 会出现死锁 锁定粒度界于表锁和行锁之间 并发度一般
表锁更适合以查询为主 只有少量按索引条件更新数据的应用 如OLAP系统
行级锁则更适合有大量按索引条件并发更新少量不同数据 同时又有并发查询的应用 如一些在线事务处理(OLTP)系统
表级锁有两种
表共享读锁 表独占写锁
给表 加共享读锁
lock table 表名 read
1. lock table testmysam READ 启动另外一个session select * from
testmysam 可以查询
2. insert into testmysam value(2);
update testmysam set id=2 where id=1;
报错
3.在另外一个session中
insert into testmysam value(2); 等待
4.在同一个session中
insert into testdemo value(2,'2','3'); 报错
select * from testdemo ; 报错
5.在另外一个session中
insert into testdemo value(2,'2','3'); 成功
6.加索在同一个session 中 select s.* from testmysam s 报错
lock table 表名 as 别名 read;
查看 show status LIKE 'table_locks_waited' 表被锁过几次
表独占写锁
lock table 表名 write
1.lock table testmysam WRITE
在同一个session中
insert testmysam value(3);
delete from testmysam where id = 3
select * from testmysam
2.对不同的表操作(报错)
select s.* from testmysam s
insert into testdemo value(2,'2','3');
3.在其他session中 (等待)
select * from testmysam
对MyISAM 表的读操作 不会阻塞其他用户对同一表的读请求 但会阻塞对同一表的写请求
对MyISAM 表的读操作 不会阻塞当前session 对表读 但对表的修改会报错
一个session 使用lock table 命令给表f加了读锁 这个session 可查询锁定表中的记录 但更新或访问其他表都会提示错误
另外一个session 可以查询表中的记录 但更新就会出现锁等待
对MYISAM 表的写操作 则会阻塞其他用户对同一表的读和写操作
对MySAM 表的写操作 当前session可以对本表做CRUD 但对其他表操作则会报错
InnoDB 行锁
共享锁 读锁 当一个事务对某几行上读锁时 ,允许其他事务对这几行进行读操作 但不允许其进行写操作 也不允许其他事务给这几行上排它锁 但允许上读锁
lock in share mode
例 select * from 表 where 条件 lock in share mode
排它锁 写锁 当一个事务对某几个上写锁时 ,不允许其他事务写 但允许读 更不允许其他事务给这几行上任何锁 包括写锁
for update
例 select * from 表 where 条件 for update
两个事务不能锁同一个索引
insert delete update 在事务中都会自动默认加上排它锁
行锁必须有索引才能实现 否则会自动锁全表 那么就不是行锁了
1.
BEGIN
select * from testdemo where id =1 for update
在另外一个session中
update testdemo set c1 = '1' where id = 2 成功
update testdemo set c1 = '1' where id = 1 等待
2.BEGIN
update testdemo set c1 = '1' where id = 1
在另外一个session中
update testdemo set c1 = '1' where id = 1 等待
3.
BEGIN
update testdemo set c1 = '1' where c1 = '1'
在另外一个session中
update testdemo set c1 = '2' where c1 = '2' 等待
开启一个新的事务时会解锁表
1.先来看下行锁
第一个session中
select * from testdemo where id =1 for update
第二个session
select * from testdemo where id =1 lock in share mode
回到第一个session UNLOCK TABLES 并不会解锁
使用commit 或者 begin或者ROLLBACK 才会解锁
2.再来看下表锁
lock table testdemo WRITE
使用commit,ROLLBACK 并不会解锁
使用UNLOCK TABLES 或者begin会解锁