Mysql--行锁,表锁的理解&实践

写在前面

  • 命令行工具使用的是cmder,具体的安装使用参考:cmder的安装以及一些简单的配置
  • Mysql使用的版本是8.0.13。
  • Mysql事物的隔离级别采用的是默认的隔离级别:REPEATABLE READ(可重复读)
  • 本篇文章中用到的数据库表的结构以及表的数据:
CREATE TABLE `student` (
  `sno` char(10) NOT NULL,
  `sname` char(10) DEFAULT NULL,
  `ssex` char(3) NOT NULL,
  `sage` int(11) NOT NULL,
  `sdett` char(10) NOT NULL,
  PRIMARY KEY (`sno`),
  KEY `sname` (`sname`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

在这里插入图片描述
本文章Sql语句中的所有的数据记录基本上就这两条数据。

  • 截图中的标号代表执行的先后顺序。
  • 本机环境为Windows。
  • 本篇博客中有哪个地方写的不对,还请各位博主指出,感谢。

目的

主要是为了讨论下在Mysql事务查询中,什么时候Mysql会加行锁,什么时候会加表锁,自己通过一个表的一些操作会去一一的说明。

Mysql的一些知识

1,Mysal默认的存储引擎是InnoDB,那么InnoDB与MyISAM存储引擎其中一个区别就是说在InnoDB中支持行锁和事务。
2,通过命令行的方式创建事物的命令是start transaction;,提交事物的命令行语句是commit;
3,在Mysql中,行锁本质上是通过索引项去添加的。

Mysql行锁的讨论

  • 问题1:通过索引查询数据会出现行锁吗?
    首先我们先创建两个事务,如下图所示:
    事务1:
    在这里插入图片描述
    事务2:
    在这里插入图片描述
    现在在事务1中进行查询语句:如下图所示:
    Mysql--行锁,表锁的理解&实践_第1张图片
    假如说select查询语句会对表记录进行加行锁的话,那么我在事务2中对sname = 'lihua’的这条记录进行修改的时候就会出现阻塞的现象,测试如下:我在事务2中输入如下图所示的语句:
    在这里插入图片描述
    发现当前更新语句并没有出现阻塞的情况,其实也就说明select语句并不会对行记录进行加行锁的操作。
    为了进一步的说明,我们可以通过使用下面的sql语句查看每个事务的阻塞情况:
    select * from INNODB_TRX \G
    截图如下:
    Mysql--行锁,表锁的理解&实践_第2张图片你会发现每个事务都是处于running状态(因为这两个事务我都还没有commit)。因此从这里我们也可以认为select语句不会对表中的记录加行锁。
  • 问题2:通过索引修改数据会出现行锁吗?
    为了测试这种情况,我们需要在事务1中和事务2中分别执行如下图的sql语句:

在这里插入图片描述
图中标号1 处是通过sname的索引去修改表中sname='lihua’的行记录,从图中标号2处我们可以看出修改的语句是成功的,没有阻塞状态,从这里我们可以推断出,通过update语句进行更新表记录(通过索引去update)是不会进行加表锁的,同理从标号为 3 的地方可以看出,事务2想要去更新sname='lihua’的记录的时候,出现了阻塞的状态,所以从这里我们可以看出通过索引去update行记录是会对对应的记录进行加行锁的设置。
我们也可以通过select * from INNODB_TRX \G 语句进行查看事务的阻塞状态:
Mysql--行锁,表锁的理解&实践_第3张图片
从上面的红色方框中可以看出,事务2在执行第二次update操作的时候是出现了阻塞的状态。

  • 问题3:通过索引删除数据会出现行锁吗?
    事务1和事务2分别执行如下图所示:

    从上图中标号 1,2,3可以看出根据索引删除行记录的时候会触发行锁,并不会触发表锁。

Mysql表锁的讨论

  • 问题1:通过主键修改数据会出现表锁吗?
    主键其实跟索引差不多,都是用来去标记某一行记录的,如果通过主键去进行修改或者删除会不会出现和索引相同的结论呢?如下图所示:
    在这里插入图片描述
    从上图中我们可以看出,标号 1 处执行过后执行标号 2 的时候会阻塞事务2的执行,可以判断出如果通过主键去修改某一条行记录的话,那么此时当前事务就会锁住整张表也即表锁,这点是和通过索引去修改的时候是不一样的。同理,通过主键去删除某一条记录的时候也是会锁住整张表的,如下图所示:
    在这里插入图片描述
  • 问题2:不通过索引更新数据会出现表锁吗?
    前面我们都是讨论的是通过索引或者主键去对表进行修改,那么加入说如果只是通过普通的字段去进行对表中记录的修改,会有怎么的变化呢?
    Mysql--行锁,表锁的理解&实践_第4张图片
    从上图中标号 1,2 中我们可以看出,事务2处于阻塞状态,则通过普通的字段去更新数据的时候,是会对整张表加锁的。同理通过普通字段删除表记录实一样的,也是加表锁。这里就不截图了。

补充:无论是加行锁,或者是表锁,都不会去阻塞读操作,因为Mysql中会存在数据快照这样一种方式去供读操作去查询,因此不会阻塞。

你可能感兴趣的:(Mysql,Mysql)