MySQL innoDB引擎锁机制(一) —— 行锁和表锁

我们都知道,MyISAM引擎使用的是表锁,而innoDB最小粒度为行锁。但在实际使用中我们有时发现就算我们操作的是不同行的数据,还是会发生锁表。我们先来看一个例子。

session1开启事务并更新id=1的数据:

session2开启事务,并更新id=2的数据,但session2被阻塞了:

不是说innoDB支持行锁吗,我们这里明明更新的不是同一条数据,为什么还会被阻塞。其实这是因为MySQL innoDB给数据加锁的方式和oracle不一样。oracle是给这条数据行加锁,而innoDB是给索引上的索引项加锁来实现的。简单的说就是:如果我们的语句无法命中索引,innoDB就会锁表。我们给innodb_lock表的id列加上索引:

session1开启事务并更新id=1的数据:

session2开启事务,并更新id=2的数据,此时更新成功:



上面说到innoDB的行锁是针对索引加锁,而不是具体的记录。所以如果即使是不同的记录,只要访问的是同一个索引也会导致阻塞。还是用上面的例子,我们先插入一条id相同的数据。

session1开启事务并更新id=1 and name=my1的数据:

session2开启事务,并更新id=1 and name=my5的数据,但session2被阻塞了:

我们再尝试去更新name=my5的数据,但不用id去匹配,session2还是被阻塞。这种阻塞是因为name列上无索引,所以该update会尝试锁表,但由于已经存在行锁,所以锁表会被阻塞:

从上面看出,innoDB锁的就是索引,而不是表中的具体数据。由于session1锁了id=1的索引,又由于name并无索引,所以他们虽然不是同一条记录,但他们id是一样的就会导致阻塞。



上面说的都是单列索引的情况,如果表上有多列都有索引会怎么样呢。当表有多个索引时,可以使用不同的索引锁定不同行。我们修改下表结构,加入一列addr,然后给id和name都加上索引。

我们先来看看使用一列索引的情况。session1更新id=1 and addr=addr1的行:

session2去更新name=my4的行,被阻塞。因为虽然MySQL尝试去锁行但该行id=1的索引已经被锁定:

session2再用addr=addr4去更新,被阻塞。这里被阻塞是该语句尝试去锁表,因为addr列上无索引:

我们再来看看使用多列索引的情况。session1更新id=1 and name=my1的行:

session2去更新name=my4的行,成功。因为id和name都有索引,所以当我们以它们为条件时相当于形成了一个联合索引,只精确的锁了id=1 and name=my1的联合索引。

session2再用addr=addr4去更新,还是被阻塞。这里被阻塞是该语句尝试去锁表,因为addr列上无索引:



总结:MySQL innoDB给数据加锁的方式和oracle不一样。oracle是给这条数据行加锁,而innoDB是给索引上的索引项加锁来实现的。简单的说就是:如果我们的语句无法命中索引,innoDB就会锁表。我们可以通过几个简单地步骤来判断innoDB会锁哪些表:1.去掉where条件中没有索引的列 2.用剩下的条件查询出来的记录就是innoDB会锁的行。

时间: 2024-12-28 01:42:13

MySQL innoDB引擎锁机制(一) —— 行锁和表锁的相关文章

巧用MySQL InnoDB引擎锁机制解决死锁问题(转)

该文会通过一个实际例子中的死锁问题的解决过程,进一步解释innodb的行锁机制 最近,在项目开发过程中,碰到了数据库死锁问题,在解决问题的过程中,笔者对MySQL InnoDB引擎锁机制的理解逐步加深. 案例如下: 在使用Show innodb status检查引擎状态时,发现了死锁问题: *** (1) TRANSACTION: TRANSACTION 0 677833455, ACTIVE 0 sec, process no 11393, OS thread id 278546 starti

详解 MySql InnoDB 中的三种行锁(记录锁、间隙锁与临键锁)

详解 MySql InnoDB 中的三种行锁(记录锁.间隙锁与临键锁) 前言 InnoDB 通过 MVCC 和 NEXT-KEY Locks,解决了在可重复读的事务隔离级别下出现幻读的问题.MVCC 我先挖个坑,日后再细讲,这篇文章我们主要来谈谈那些可爱的锁. 什么是幻读? 幻读是在可重复读的事务隔离级别下会出现的一种问题,简单来说,可重复读保证了当前事务不会读取到其他事务已提交的 UPDATE 操作.但同时,也会导致当前事务无法感知到来自其他事务中的 INSERT 或 DELETE 操作,这就

大话Linux内核中锁机制之RCU、大内核锁

大话Linux内核中锁机制之RCU.大内核锁 在上篇博文中笔者分析了关于完成量和互斥量的使用以及一些经典的问题,下面笔者将在本篇博文中重点分析有关RCU机制的相关内容以及介绍目前已被淘汰出内核的大内核锁(BKL).文章的最后对<大话Linux内核中锁机制>系列博文进行了总结,并提出关于目前Linux内核中提供的锁机制的一些基本使用观点. 十.RCU机制 本节将讨论另一种重要锁机制:RCU锁机制.首先我们从概念上理解下什么叫RCU,其中读(Read):读者不需要获得任何锁就可访问RCU保护的临界

MySQL Study之--MySQL innodb引擎备份工具XtraBackup之一(Install)

MySQL Study之--MySQL innodb引擎备份工具XtraBackup之一(Install) Xtrabackup是一个对InnoDB做数据备份的工具,支持在线热备份(备份时不影响数据读写),是商业备份工具InnoDB Hotbackup的一个很好的替代品. Xtrabackup有两个主要的工具:xtrabackup.innobackupex (1)xtrabackup只能备份InnoDB和XtraDB两种数据表,而不能备份MyISAM数据表 (2)innobackupex-1.5

mysql innodb 引擎内存分配项

MySQL做为最流行的开源数据库,innodb在5.6开始已成为默认引擎,在5.7中系统吧引擎也有myisam改为innodb,可以看出innodb引擎现在已经可以满足绝大部分的业务需求,内存分配直接影响MySQL整体运行效率,有innodb_buffer,还有各种cache_size,这些选项都需要合理分配,合理利用服务器有限的内存让MySQL跑的更嗨皮,直接影响的选项有下面几个: innodb_buffer_pool_size:缓冲区,存放表数据.索引数据,大小至关重要,直接影响sql执行时

Mysql InnoDB引擎的读锁

Mysql官方手册读锁说明 如果,在一个相同的事务中,你查询数据,然后插入/更新与此数据相关的数据,那个通常的SELECT语句不会给我们足够的保护.因为在我们当前事务的SELECT和UPDATE之间的时间段内,其他的事务可能会更新/删除我们刚刚读取到的行.而我们根本不会察觉. InnoDB支持两种类型的读锁,可以给我们提供足够的安全. 1.SELECT ... LOCK IN SHARE MODE  这是共享锁,在读取的任何数据上设定一个共享模式的锁.其他事务可以读取这些数据.但是不能修改这些数

(转)SQL SERVER的锁机制(一)——概述(锁的种类与范围)

锁定:通俗的讲就是加锁.锁定是 Microsoft SQL Server 数据库引擎用来同步多个用户同时对同一个数据块的访问的一种机制. 定义:当有事务操作时,数据库引擎会要求不同类型的锁定,如相关数据行.数据页或是整个数据表,当锁定运行时,会阻止其他事务对已经锁定的数据行.数据页或数据表进行操作.只有在当前事务对于自己锁定的资源不在需要时,才会释放其锁定的资源,供其他事务使用. 一.锁的种类与范围(如下表) 锁类型 说明 共享 (S) 用于不更改或不更新数据的读取操作,如 SELECT 语句.

SQL SERVER的锁机制(一)——概述(锁的种类与范围)

锁定:通俗的讲就是加锁.锁定是 Microsoft SQL Server 数据库引擎用来同步多个用户同时对同一个数据块的访问的一种机制. 定义:当有事务操作时,数据库引擎会要求不同类型的锁定,如相关数据行.数据页或是整个数据表,当锁定运行时,会阻止其他事务对已经锁定的数据行.数据页或数据表进行操作.只有在当前事务对于自己锁定的资源不在需要时,才会释放其锁定的资源,供其他事务使用. 一.锁的种类与范围(如下表) 锁类型 说明 共享 (S) 用于不更改或不更新数据的读取操作,如 SELECT 语句.

mysql InnoDB引擎 共享表空间和独立表空间(转载)

PS:innodb这种引擎,与MYISAM引擎的区别很大.特别是它的数据存储格式等.对于innodb的数据结构,首先要解决两个概念性的问题: 共享表空间以及独占表空间. 1.什么是共享表空间和独占表空间 共享表空间以及独占表空间都是针对innodb表的数据存储而言的,ibdata1为innodb引擎的存储数据与索引的数据文件,ib_logfile0与ib_logfile1为innodb引擎使用的日志文件共享表空间: mysql服务器中所有数据库的innodb表(数据,索引)全部放在一个文件中,默