学习mysql不得不学习mysql行级锁,目前Innodb是支持行级锁的引擎,下面一起学习一下。

InnoDB 引擎是支持行级锁的,而 MyISAM 引擎并不支持行级锁。

普通的 select 语句是不会对记录加锁的,因为它属于快照读。如果要在查询时对记录加行锁,可以使用下面这两个方式,这种查询会加锁的语句称为锁定读

1
2
3
4
5
//对读取的记录加共享锁
select ... lock in share mode;

//对读取的记录加独占锁
select ... for update;

上面这两条语句必须在一个事务中,因为当事务提交了,锁就会被释放,所以在使用这两条语句的时候,要加上 begin、start transaction 或者 set autocommit = 0。

共享锁(S锁)满足读读共享,读写互斥。独占锁(X锁)满足写写互斥、读写互斥。

什么是S锁?

在数据库管理系统和并发控制中,共享锁(通常称为S锁)是一种用于保证数据一致性的机制。它允许多个事务同时读取数据,但在持有共享锁的事务完成之前,不允许任何事务修改该数据。

共享锁有如下特点:

允许共享读取:多个事务可以同时持有共享锁,从而允许它们同时读取数据。这不会造成数据的不一致,因为没有事务可以在此时修改数据。

阻止修改:即使多个事务持有共享锁,也不能有任何事务对数据进行写入或修改,直到所有持有共享锁的事务都释放锁为止。

互斥:如果一个事务持有共享锁,则其他事务不能获得排他锁(X锁)。排他锁允许事务对数据进行修改,并会阻止其他事务对该数据进行任何类型的锁操作(包括共享锁和其他排他锁)。

什么是X锁?

在数据库管理系统和并发控制中,排他锁(通常称为X锁)是一种更为严格的锁定机制,用于确保数据的完整性和一致性。

阻止所有其他操作:持有排他锁的事务可以读取和修改数据。与此同时,其他任何事务都不能对这块数据进行读取或修改操作,直到排他锁被释放。

互斥性:在一个事务持有排他锁期间,其他事务不能获得该数据的任何类型的锁,包括共享锁和其他排他锁。这保证了对数据的完全控制,防止了并发操作引起的冲突和数据不一致。

独占访问:因为排他锁会阻止其他事务的访问,所以它适用于需要对数据进行写操作的场景,如更新、删除等。

锁升级:在某些数据库系统中,当事务需要从共享锁升级为排他锁时,可能会导致锁的升级过程,期间可能需要等待其他持有共享锁的事务完成。

Mysql 行级锁有哪些?

1. Record Lock,记录锁,也就是仅仅把一条记录锁上;

Record Lock 称为记录锁,锁住的是一条记录。而且记录锁是有 S 锁和 X 锁之分的:

例如以下语句:

1
2
mysql > begin;
mysql > select * from t_test where id = 1 for update;

记录锁
事务会对表中主键 id = 1 的这条记录加上 X 型的记录锁,如果这时候其他事务对这条记录进行删除或者更新操作, 那么这些操作都会被阻塞。
注意,其他事务插入一条 id = 1 的新记录并不会被阻塞,而是会报主键冲突的错误,这是因为主键有唯一性的约束。

2. Gap Lock,间隙锁,锁定一个范围,但是不包含记录本身;

Gap Lock 称为间隙锁,只存在于可重复读隔离级别,目的是为了解决可重复读隔离级别下幻读的现象。

假设,表中有一个范围 id 为(3,5)间隙锁,那么其他事务就无法插入 id = 4 这条记录了,这样就有效的防止幻读现象的发生。

间隙锁

3. Next-Key Lock:Record Lock + Gap Lock 的组合,锁定一个范围,并且锁定记录本身。

Next-Key Lock 称为临键锁,是 Record Lock + Gap Lock 的组合,锁定一个范围,并且锁定记录本身。

假设,表中有一个范围 id 为(3,5] 的 next-key lock,那么其他事务即不能插入 id = 4 记录,也不能修改 id = 5 这条记录。

临键锁

所以,next-key lock 即能保护该记录,又能阻止其他事务将新纪录插入到被保护记录前面的间隙中。

next-keyW lock 是包含间隙锁+记录锁的,如果一个事务获取了 X 型的 next-key lock,那么另外一个事务在获取相同范围的 X 型的 next-key lock 时,是会被阻塞的。


好了今天只是其中的一小步分暂时整理到这,后续会继续积累总结