Mysql锁机制是保证数据库并发访问的重要手段,它包括行锁和表锁两种形式,同时也存在死锁的情况。下面我们来一一讲解。
行锁
行锁指的是针对数据库表中的行,对其进行锁定。行锁机制的粒度很细,能够互不影响的锁定多个行。MySQL行级锁使用的是innodb
引擎。
在MySQL中,行锁存在一种“共享锁”和“排它锁”的两种形式。
共享锁
共享锁是针对行级别的读加锁,多个事务可以同时持有行的共享锁,但是会导致并发降低。
示例:
-- Session A
begin;
select * from `table` where `column1` = 'value' for update; -- 针对该行加锁
-- Session B
begin;
select * from `table` where `column1` = 'value' for update; -- 暂时无法进行加锁,等待Session A释放锁
排它锁
排它锁是针对行级别的修改加锁,同一时刻只能有一个事务持有这个锁,可以实现写操作,但会导致读操作的阻塞。
示例:
-- Session A
begin;
update `table` set `column1` = 'value2' where `column1` = 'value1'; -- 这个过程会对该行进行排它锁的加锁操作
-- Session B
begin;
select * from `table` where `column1` = 'value1' for update; -- 暂时无法进行加锁,等待Session A释放锁
表锁
表锁是对整张表进行锁定,表锁机制的粒度很大,能够互不影响的锁定多个表。但是,其并发性较差,一次只能有一个线程对其进行操作。在MySQL中,MyISAM
和MEMORY
存储引擎是使用表锁。
示例:
-- Session A
begin;
lock tables `table1` write; -- 对`table1`进行写操作,会对整张表加锁
-- Session B
begin;
lock tables `table1` write; -- 暂时无法进行加锁,等待Session A释放锁
死锁
死锁是指两个或多个事务在执行操作时,因相互等待对方释放锁而陷入无限等待的状态。如果不释放锁,这些事务将永远处于等待状态,无法结束。
示例:
-- Session A
begin;
update `table1` set `column1` = 'value1' where `id` = 1; -- 对`table1`进行排它锁的加锁操作
-- Session B
begin;
update `table2` set `column2` = 'value2' where `id` = 2; -- 对`table2`进行排它锁的加锁操作
-- Session A(由于需要修改`table2`中的数据,因此需要对`table2`加锁,此时锁被Session B占用,A需要等待)
update `table2` set `column2` = 'value3' where `id` = 3;
-- Session B(由于需要修改`table1`中的数据,因此需要对`table1`加锁,此时锁被Session A占用,B需要等待)
update `table1` set `column1` = 'value2' where `id` = 2;
在以上示例中,Session A需要修改table2
中的数据,因此需要先对table2
加锁,但是锁被Session B占用,因此需要等待。同时,Session B也需要修改table1
中的数据,也需要等待Session A的锁释放。这样两个Session就出现了互相等待的情况,造成了死锁。
为了预防死锁,在设计数据库时,应该尽量避免跨表查询或者修改数据,同时尽量使用行级锁进行操作。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Mysql锁机制之行锁、表锁、死锁的实现 - Python技术站