Innodb 行锁与表锁

2024-02-27 09:38
文章标签 innodb 行锁 表锁

本文主要是介绍Innodb 行锁与表锁,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

行锁与表锁

InnoDB默认是行级别的锁,当有明确指定的主键时候,是行级锁。否则是表级别。

#for update的注意点
for update 仅适用于InnoDB,并且必须开启事务,在begin与commit之间才生效。

要测试for update的锁表情况,可以利用MySQL的Command Mode,开启二个视窗来做测试。

1、只根据主键进行查询,并且查询到数据,主键字段产生行锁。

begin;

select * from goods where id = 1 for update;

commit;

2、只根据主键进行查询,没有查询到数据,不产生锁。

begin;

select * from goods where id = 1 for update;

commit;

 

3、根据主键、非主键含索引(name)进行查询,并且查询到数据,主键字段产生行锁,name字段产生行锁。

begin;

select * from goods where id = 1 and name='prod11' for update;

commit;

 

4、根据主键、非主键含索引(name)进行查询,没有查询到数据,不产生锁。

begin;

select * from goods where id = 1 and name='prod12' for update;

commit;

 

5、根据主键、非主键不含索引(name)进行查询,并且查询到数据,如果其他线程按主键字段进行再次查询,则主键字段产生行锁,如果其他线程按非主键不含索引字段进行查询,则非主键不含索引字段产生表锁,如果其他线程按非主键含索引字段进行查询,则非主键含索引字段产生行锁,如果索引值是枚举类型,mysql也会进行表锁,这段话有点拗口,大家仔细理解一下。

 

begin;

select * from goods where id = 1 and name='prod11' for update;

commit;

 

6、根据主键、非主键不含索引(name)进行查询,没有查询到数据,不产生锁。

 

begin;

select * from goods where id = 1 and name='prod12' for update;

commit;

 

7、根据非主键含索引(name)进行查询,并且查询到数据,name字段产生行锁。

 

begin;

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

commit;

 

8、根据非主键含索引(name)进行查询,没有查询到数据,不产生锁。

begin;

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

commit;

 

9、根据非主键不含索引(stock)进行查询,并且查询到数据,stock字段产生表锁。

begin;

select * from goods where stock='1000' for update;

commit;

 

10、根据非主键不含索引(stock)进行查询,没有查询到数据,stock字段产生表锁。

begin;

select * from goods where stock='2000' for update;

commit;

 

11、只根据主键进行查询,查询条件为不等于,并且查询到数据,主键字段产生表锁。

begin;

select * from goods where id <> 1 for update;

commit;

11.1 

begin;

select * from goods where id < 5 and id <> 1 for update;

commit;

这条查询仅仅会返回2 ~ 4之间的行,但是实际上获取了 1 ~ 4之间的行的排他锁。InnoDB会锁住第1行  ---- 底层存储引擎的操作是“从索引的开头开始获取满足条件id < 5的记录” ,服务器并没有告诉InnoDB可以过滤第1行的where条件, 需要MySQL服务器将存储引擎返回行以后再应用where过滤条件(Extra  Using where)。

 

12、只根据主键进行查询,查询条件为不等于,没有查询到数据,主键字段产生表锁。

begin;

select * from goods where id <> 1 for update;

commit;

 

13、只根据主键进行查询,查询条件为 like,并且查询到数据,主键字段产生表锁。

begin;

select * from goods where id like '1' for update;

commit;

 

14、只根据主键进行查询,查询条件为 like,没有查询到数据,主键字段产生表锁。

 

begin;

select * from goods where id like '1' for update;

commit;

总结

1、InnoDB行锁是通过给索引上的索引项加锁来实现的,只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁。

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

3、当表有多个索引的时候,不同的事务可以使用不同的索引锁定不同的行,另外,不论是使用主键索引、唯一索引或普通索引,InnoDB都会使用行锁来对数据加锁。

4、即便在条件中使用了索引字段,但是否使用索引来检索数据是由MySQL通过判断不同执行计划的代价来决定的,如果MySQL认为全表扫描效率更高,比如对一些很小的表,它就不会使用索引,这种情况下InnoDB将使用表锁,而不是行锁。因此,在分析锁冲突时,别忘了检查SQL的执行计划,以确认是否真正使用了索引。

5、检索值的数据类型与索引字段不同,虽然MySQL能够进行数据类型转换,但却不会使用索引,从而导致InnoDB使用表锁。通过用explain检查两条SQL的执行计划,我们可以清楚地看到了这一点。(此条本地验证后发现 数据库类型为varchar时 查询用 数字类型时用不了索引 。但数据库类型为int、  datetime时 查询类型为字符串 也可以走索引)

这篇关于Innodb 行锁与表锁的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/751978

相关文章

MySQL之InnoDB存储引擎中的索引用法及说明

《MySQL之InnoDB存储引擎中的索引用法及说明》:本文主要介绍MySQL之InnoDB存储引擎中的索引用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录1、背景2、准备3、正篇【1】存储用户记录的数据页【2】存储目录项记录的数据页【3】聚簇索引【4】二

MySQL中的InnoDB单表访问过程

《MySQL中的InnoDB单表访问过程》:本文主要介绍MySQL中的InnoDB单表访问过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、访问类型【1】const【2】ref【3】ref_or_null【4】range【5】index【6】

MySQL之InnoDB存储页的独立表空间解读

《MySQL之InnoDB存储页的独立表空间解读》:本文主要介绍MySQL之InnoDB存储页的独立表空间,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、独立表空间【1】表空间大小【2】区【3】组【4】段【5】区的类型【6】XDES Entry区结构【

关于MyISAM和InnoDB对比分析

《关于MyISAM和InnoDB对比分析》:本文主要介绍关于MyISAM和InnoDB对比分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录开篇:从交通规则看存储引擎选择理解存储引擎的基本概念技术原理对比1. 事务支持:ACID的守护者2. 锁机制:并发控制的艺

MySQL启动报错:InnoDB表空间丢失问题及解决方法

《MySQL启动报错:InnoDB表空间丢失问题及解决方法》在启动MySQL时,遇到了InnoDB:Tablespace5975wasnotfound,该错误表明MySQL在启动过程中无法找到指定的s... 目录mysql 启动报错:InnoDB 表空间丢失问题及解决方法错误分析解决方案1. 启用 inno

Mysql中InnoDB与MyISAM索引差异详解(最新整理)

《Mysql中InnoDB与MyISAM索引差异详解(最新整理)》InnoDB和MyISAM在索引实现和特性上有差异,包括聚集索引、非聚集索引、事务支持、并发控制、覆盖索引、主键约束、外键支持和物理存... 目录1. 索引类型与数据存储方式InnoDBMyISAM2. 事务与并发控制InnoDBMyISAM

MySQL InnoDB引擎ibdata文件损坏/删除后使用frm和ibd文件恢复数据

《MySQLInnoDB引擎ibdata文件损坏/删除后使用frm和ibd文件恢复数据》mysql的ibdata文件被误删、被恶意修改,没有从库和备份数据的情况下的数据恢复,不能保证数据库所有表数据... 参考:mysql Innodb表空间卸载、迁移、装载的使用方法注意!此方法只适用于innodb_fi

MySQL表锁、页面锁和行锁的作用及其优缺点对比分析

《MySQL表锁、页面锁和行锁的作用及其优缺点对比分析》MySQL中的表锁、页面锁和行锁各有特点,适用于不同的场景,表锁锁定整个表,适用于批量操作和MyISAM存储引擎,页面锁锁定数据页,适用于旧版本... 目录1. 表锁(Table Lock)2. 页面锁(Page Lock)3. 行锁(Row Lock

InnoDB的多版本一致性读的实现

InnoDB是支持MVCC多版本一致性读的,因此和其他实现了MVCC的系统如Oracle,PostgreSQL一样,读不会阻塞写,写也不会阻塞读。虽然同样是MVCC,各家的实现是不太一样的。Oracle通过在block头部的事务列表,和记录中的锁标志位,加上回滚段,个人认为实现上是最优雅的方式。 而PostgreSQL则更是将多个版本的数据都放在表中,而没有单独的回滚段,导致的一个结果是回滚非

MySQL技术内幕_innodb存储引擎

MySQL技术内幕_innodb存储引擎 INNODB innodb中如果表没有主键 表是否由 非空唯一键,有则该字段为主键没有,则自动创建一个6字节大小的指针 innodb存储引擎的所有数据都存储在表空间中,表空间由段,区,页(块)组成。 如果启用了 innodb_file_per_table, 则每张表内的数据可以单独放在一个表空间中即使启用了上面参数,共享表空间也会因为 系统事务信息