mysql 开发进阶篇系列 8 锁问题 (Innodb 行锁实现方式)
一.概述
Innodb 行锁是通过给索引上的索引项加锁来实现的。这一点与(oracle,sql server)不同后者是通过在数据块中对相应的数据行加锁。这意味着只有通过索引条件检索数据,innodb才使用行级锁,否则 innodb将使用表锁。
在实际应用中,特别要注意innodb行锁的这一特性,不然的话,可能导致大量的锁冲突,从而影响并发性能。下面来实际演示说明:
1. innodb 的表条件CityCode不使用索引时,使用的是表锁例子
-- 查询表中数据共二条 SELECT * FROM city;
-- 条件字段CityCode不走索引 EXPLAIN SELECT * FROM city WHERE CityCode='001'
会话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='001'
会话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 长沙 |
上一篇: Nhibernate学习的第一天
下一篇: php实现支付宝当面付(扫码支付)功能
推荐阅读
-
mysql 开发进阶篇系列 7 锁问题
-
mysql 开发进阶篇系列 14 锁问题(避免死锁,死锁查看分析)
-
mysql 开发进阶篇系列 7 锁问题 (lock in share mode与for update)演示
-
mysql 开发进阶篇系列 8 锁问题 (Innodb 行锁实现方式)
-
mysql 开发进阶篇系列 15 锁问题 (总结)
-
mysql 开发进阶篇系列 10 锁问题 (相同索引键值或同一行或间隙锁的冲突)
-
mysql 开发进阶篇系列 11 锁问题 (恢复和复制的需要,对锁机制的影响)
-
mysql 开发进阶篇系列 13 锁问题(关于表锁,死锁示例,锁等待设置)
-
mysql 开发进阶篇系列 12 锁问题(隔离级别下锁的差异)
-
mysql 开发进阶篇系列 6 锁问题