写点什么

MySQL 原理与优化:Update 优化

作者:崔皓
  • 2022 年 8 月 10 日
    湖北
  • 本文字数:977 字

    阅读完需:约 3 分钟


谈到 Update 语句大家可能不会陌生,很多情况下我们都会使用它来更新 table 中的记录。一般而言我们会使用 innodb 的存储引擎,innodb 引擎是基于行锁的,具体一点说是针对索引来加锁的(保证锁不能失效),并不是针对记录加锁,如果对于没有建立索引的字段进行过滤操作,从而执行 update 的话,会导致表锁 。

今天就看看在使用 innodb 的时候如何使用 update 语句。


已经存在 course 表,其内容如下:



目前该表没有加任何的索引,默认情况下 id 是表的索引。

接着让我们分别开启两个事务(两个客户端),分别执行下述指令。

开启第一个事务

begin;

update course set name = 'Java' where id = 1;



开启另外一个事务

begin;

update course set name = 'Spark' where id = 4;


两个事务都可以执行,然后再分别执行两个事务的 commit 操作,就可以看到更新的结果。



两个事务能够并行执行的条件是 id 是表 course 的索引,可以由于 update id 分别对应 2 和 4 ,只是针对这两行记录进行加锁。

接着让我们看看另外一个例子,依旧是开启两个事务,但是 where 条件选择使用 name ,而且 name 没有作为 course 表的索引。

开启一个事务:

begin;

update course set name = 'Vue.js' where name = 'PHP';

然后再执行另外一个事务

begin;

update course set name = 'SQLServer' where name = 'MySQL';

此时在执行第二个事务的 update 语句的时候,会被阻塞。就是因为针对 name 的过滤条件并不是 course 的索引,此时的 update 语句进行了锁表的操作,必须等第一个事务 commit 之后,释放掉表锁,第二个事务才能继续执行。



为了让两个事务能够并行执行,我们将 name 加入到 course 的索引中去。

create index index_name on course(name);

show index from course;



接着再执行刚才的两个事务,这两个事务分别对不同的记录进行更新,where 中的 name 条件不一样的情况下,也不会出现锁表的情况,这是因为将 name 作为了 course 的索引。

为了演示方便,这里我们将更新的条件调整一下:

开启一个事务:

begin;

update course set name = 'PHP' where name = 'Vue.js';

然后再执行另外一个事务

begin;

update course set name = 'MySQL' where name = 'SQLServer';

结果和我们预想的一样,两个事务可以并行执行,同时在 commit 之后能够看到结果。


总结一下, 如果使用 innodb 存储引擎,update 的时候存在 where 条件的情况下,条件字段是索引的情况可以提升更新的效率,避免锁表的情况发生。

发布于: 刚刚阅读数: 3
用户头像

崔皓

关注

还未添加个人签名 2019.01.02 加入

还未添加个人简介

评论

发布
暂无评论
MySQL 原理与优化:Update 优化_崔皓_InfoQ写作社区