MySQL 锁

锁是计算机协调多个进程或线程并发访问某一资源的机制

在数据库中,数据也是一种供许多用户共享的资源。如何保证数据并发访问得一致性,有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素 

锁对数据库而言显得尤其重要,也更加复杂

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会解锁

   

原文地址:https://www.cnblogs.com/qin1993/p/12090568.html