mysql 开发进阶篇系列 9 锁问题 (Innodb 行锁实现方式)

时间:2020-12-27 16:34:43

一.概述

  Innodb 行锁是通过给索引上的"索引项"加锁来实现的。这一点与(oracle,sql server)不同后者是通过在数据块中对相应的数据行加锁。这意味着只有通过索引条件检索数据,innodb才使用行级锁,否则 innodb将使用表锁。
  在实际应用中,特别要注意innodb行锁的这一特性,不然的话,可能导致大量的锁冲突,从而影响并发性能。下面来实际演示说明:

  1.  innodb 的表条件CityCode不使用索引时,使用的是表锁例子

-- 查询表中数据共二条
SELECT * FROM city;

mysql 开发进阶篇系列 9 锁问题 (Innodb 行锁实现方式)

-- 条件字段CityCode不走索引
EXPLAIN SELECT * FROM city WHERE CityCode=''

mysql 开发进阶篇系列 9 锁问题 (Innodb 行锁实现方式)

会话1

会话2

SET autocommit=0;

SELECT * FROM  city WHERE CityCode='001';

city_id      country_id        cityname CityCode

14     2       深圳         001

SET autocommit=0;

SELECT * FROM  city WHERE CityCode='002';

city_id      country_id        cityname CityCode

15     2       长沙         002

-- 加锁

SELECT cityname FROM  city WHERE CityCode='001' FOR UPDATE ;

cityname

深圳

-- 加锁

SELECT cityname FROM  city WHERE CityCode='002' FOR UPDATE ;

等待...

错误代码: 1205

Lock wait timeout exceeded; try restarting transaction

    通过上面的案例 会话1只给一行加了排它锁, 但会话2在请求其它行的排他锁时,却出现了锁等待。原因就是在没有索引的情况下,innodb只能使用表锁。

  2. innodb 的表条件CityCode使用索引时,使用的是行锁例子

-- 添加索引
ALTER TABLE city ADD INDEX ix_citycode(CityCode)
-- CityCode走索引
EXPLAIN SELECT * FROM city WHERE CityCode=''

mysql 开发进阶篇系列 9 锁问题 (Innodb 行锁实现方式)

会话1

会话2

SET autocommit=0;

SELECT * FROM  city WHERE CityCode='001';

city_id      country_id        cityname CityCode

14     2       深圳         001

SET autocommit=0;

SELECT * FROM  city WHERE CityCode='002';

city_id      country_id        cityname CityCode

15     2       长沙         002

-- 加锁

SELECT cityname FROM  city WHERE CityCode='001' FOR UPDATE ;

cityname

深圳

-- 加锁

SELECT cityname FROM  city WHERE CityCode='002' FOR UPDATE ;

cityname

长沙