既然是关闭订单呢,我们这里就要牵扯到,MYSQL的行锁和表锁,我们会使用select * from .. for update,这种方式,其实for update是一种悲观锁,那后续演进我们也会演进成乐观锁的,大家可以从易到难,乐观锁在表中增加一个字段,然后它是一个version,version我们可以使用时间戳毫秒数,然后来进行一个判断,再决定这个值是否要更新,是否要回滚,那么for update呢,是一个悲观锁,但是虽说简单,还是有很多要注意的点,我们来看一下,首先我们要使用Innodb引擎,那在我们项目当中,都是使用的innodb引擎,然后继续看,for update在明确主键的时候,会产生行锁,如果主键不明确的话,会产生表锁,也是一个ROW-Level Lock,一个Table-Level的Lock。
例如我们mmall_product表,有id和name,id是产品的主键,name是产品的名称,首先是明确指定主键,并且有结果集的,那就是行锁select * from mmall_product where id = '66' for update; 我们主要看where id,id是明确的主键,并且我们产品表里有这个产品,也就代表着有结果集,那么他会产生一个行锁。
- 明确指定主键,并且没有结果集,我们查一个id是-100的,id也是主键,但是呢没有结果集,不会上锁,也就是无lock,select * from mmall_product where id = -100 for update。
无主键看一下select * from mmall_product where name = 'phone' for update; name并不是主键,所以这个SQL语句会产生锁表,会把整个表锁住,所以我们在使用for update悲观锁的时候,这里一定是要注意的,如果一个不慎就会造成线上的故障。
- 那主键不明确呢 select * from mmall_product where id <> 66 for update; 其实就是不等于,代表主键不明确,不等于66的主键,非常多,所以这个锁也会变成表锁,锁住整个表,那这个是主键不明确。