innodb中的行级锁

innodb官方文档中说:

 

A record lock is a lock on an index record. For example, SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE; prevents any other transaction from inserting, updating, or deleting rows where the value of t.c1 is 10.

Record locks always lock index records, even if a table is defined with no indexes. For such cases, InnoDB creates a hidden clustered index and uses this index for record locking.

 

有点懵,求证一下

 

场景分析

假设有一张商品表 goods,它包含 id,商品名称,库存量三个字段,表结构如下:

CREATE TABLE `goods` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`name` varchar(100) DEFAULT NULL,

`stock` int(11) DEFAULT NULL,

PRIMARY KEY (`id`),

UNIQUE KEY `idx_name` (`name`) USING HASH

) ENGINE=InnoDB

插入如下数据:

INSERT INTO `goods` VALUES ('1', 'prod11', '1000');

INSERT INTO `goods` VALUES ('2', 'prod12', '1000');

INSERT INTO `goods` VALUES ('3', 'prod13', '1000');

INSERT INTO `goods` VALUES ('4', 'prod14', '1000');

INSERT INTO `goods` VALUES ('5', 'prod15', '1000');

INSERT INTO `goods` VALUES ('6', 'prod16', '1000');

INSERT INTO `goods` VALUES ('7', 'prod17', '1000');

INSERT INTO `goods` VALUES ('8', 'prod18', '1000');

INSERT INTO `goods` VALUES ('9', 'prod19', '1000');

 

1. 使用id查询(主键索引)

上锁:

begin;

select * from goods where id = 1 for update;

查询锁状态: 

innodb中的行级锁

一行被锁

 

2. 使用stock查询(非索引)

begin;

select * from goods where stock = 999 for update;

 innodb中的行级锁

 

 十行被锁,也就是说使用了表级锁

 

至于网上看到的

“由于MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是使用相同的索引键,是会出现锁冲突的。应用设计的时候要注意这一点。”

经过实验没发现会这样,文档里也没有写:

begin;

select * from goods where name='prod14' for update;

 

另一终端:

update goods set stock = stock - 1 where name = 'prod11';

innodb中的行级锁

 

 

成功,没有阻塞

 

上一篇:手写简单的php生成Html网页


下一篇:Redis1-介绍及安装