简介
锁是计算机协调多个进程或线程并发访问某一资源的机制(避免发生资源争抢)。
锁的分类
-
对数据操作的粒度分
- 表锁:操作时,会锁定整个表,不会出现死锁。
- 行锁:操作时,会锁定当前操作行,会出现死锁。
存储引擎 | 表锁 | 行锁 | 加锁方式 |
---|---|---|---|
InnoDB | 支持 | 支持 |
在执行UPDATE、DELETE、INSERT语句时,自动给涉及的数据加 排他锁 ,一般的SELECT语句 不加任何锁 |
MyISAM | 支持 | 不支持 |
在执行SELECT前会自动给涉及的所有表加 共享锁 ,在执行UPDATE、DELETE、INSERT等操作前,给涉及的表加 排他锁 |
-
对数据操作的类型分
-
共享锁
(Share Locks,读锁):事务A对数据加锁后,只能读取加锁的数据,不能读取其他数据,其他事务可以读取,均不能修改(增,删、改)。 -
排他锁
(Exclusive Locks,写锁):事务A操作时,其他事务不能对数据对象读取和修改。
-
--表锁模式
--加表锁
lock table table_name read;--共享锁
lock table table_name write;--排他锁
--
--解锁
unlock table_name;
--行锁模式
--加行锁
select * from tab_name where...lock in share mode;--加共享锁(in share mode)
select * from tab_name where...for update;--加排他锁(for update)
提醒:共享锁可以多个事务同时对同一个数据加锁,排他锁一次性只能由一个事务对数据对象加锁
死锁的三种情况及解决办法
-
第一种情况:
用户甲访问表A(锁住了A),然后访问表B;用户乙访问表B(锁住了B),然后访问表A;由于表B被用户乙锁住,用户甲必须等用户乙释放表B才能继续,同样由于表A被甲锁住,用户乙必须等用户甲释放表A才能继续,从而产生了死锁。
解决办法:
这种情况是由于程序的bug产生,应分析程序的逻辑,对于数据库的多表操作,应按照相同的顺序进行处理,尽量避免同时锁定两个资源。
-
第二种情况:
用户甲查询一条记录,然后要修改这条记录;这时用户乙修改该条记录;此时用户甲事务里锁的性质欲由共享锁变为排他锁,而用户乙里的排他锁因为甲有共享锁存在,必须等甲释放掉共享锁,而甲因为乙的排他锁而无法变为排他锁也就不可能释放共享锁。
解决办法:
①对于按钮等控件,单击后使它立即失效,不要让用户重复单击,避免同时对同一条记录进行操作。
②使用乐观锁、悲观锁进行控制
-
第三种情况:
如果在事务中执行了一条不满足条件的update语句,则执行全表扫描,把行级锁提升为表级锁,多个这样的事务执行后,很容易产生死锁和阻塞。
解决办法:
SQL语句中不要使用太复杂的关联多表的查询;使用“执行计划”对SQL语句进行分析,对于有全表扫描的SQL语句,应建立相应的索引进行优化。
版权声明:本文为qq_54414607原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。