第五章 InnoDB增强

  • 五、InnoDB增强概述
  • 5.1、集成数据字典
  • 5.2、原子DDL操作
  • 5.2.1、操作原子性实例
  • 5.3、自增列持久化
  • 5.3.1、在MySQL5.7中重现自增重复问题
  • 5.3.2、在MySQL8.0的自增的处理方式
  • 5.3.3、innodb_autoinc_lock_mode
  • 5.4、死锁检查控制
  • 5.4.1、死锁实例演示
  • 5.4.1.1、在innodb_deadlock_detect默认开启的模式下
  • 5.4.1.2、在innodb_deadlock_detect默认关闭的模式下
  • 5.5、锁定语句选项
  • 5.5.1、实例演示
  • 5.5.1.1、nowait实例演示
  • 5.5.1.2、skip locked实例演示
  • 5.5.2、注意点
  • 5.6、其他改进功能


五、InnoDB增强概述

5.1、集成数据字典

mysql8 InnoDB mysql8 innodb增强_死锁


mysql8 InnoDB mysql8 innodb增强_自增_02

5.2、原子DDL操作

mysql8 InnoDB mysql8 innodb增强_数据_03


mysql8 InnoDB mysql8 innodb增强_InnoDB增强_04

5.2.1、操作原子性实例

在MySQL5.7上测试操作,从下图中可见,我们在执行删除两张表的时候虽然报错,但是还是删除了t1表。

mysql8 InnoDB mysql8 innodb增强_数据_05


在MySQL8.0上测试;可以看到drop语句报错,查看数据库中的表发现t1并没有被删除;drop操作具有原子性;

mysql8 InnoDB mysql8 innodb增强_自增_06


mysql8 InnoDB mysql8 innodb增强_mysql8 InnoDB_07

5.3、自增列持久化

mysql8 InnoDB mysql8 innodb增强_InnoDB增强_08

5.3.1、在MySQL5.7中重现自增重复问题

创建测试表t,并添加三条测试数据;

mysql8 InnoDB mysql8 innodb增强_mysql8 InnoDB_09


然后我们删除掉id为3的数据,此时计数器应该为4,也就是下一条生成的数据的id应该为4;然后我们退出MySQL服务,然后重启MySQL服务;

mysql8 InnoDB mysql8 innodb增强_死锁_10


重新登陆MySQL后,再次插入一条数据,可以发现新插入的数据的id为3;也就是说MySQL5.7中当服务重启的时候,会将计数器的值设置为当前表中的自增字段最大值+1;

mysql8 InnoDB mysql8 innodb增强_死锁_11


此时,如果把c1字段为a的id的值改为5之后,如果我们再进行插入操作的情况下,那么就会出现主键冲突;(PS:感觉修改数据的主键的值的场景还没有在实际项目中发生过)

mysql8 InnoDB mysql8 innodb增强_数据_12


mysql8 InnoDB mysql8 innodb增强_死锁_13

5.3.2、在MySQL8.0的自增的处理方式

在MySQL8.0中重复之前的操作,在删除了id为3的数据之后,重启了MySQL的服务之后,再进行插入操作的时候,生成的数据的id的值为4;

mysql8 InnoDB mysql8 innodb增强_死锁_14


更新c1值为a的数据的id=5

mysql8 InnoDB mysql8 innodb增强_数据_15


发现并没有像再MySQL5.7中报错,而是生成了id=6的数据;

mysql8 InnoDB mysql8 innodb增强_mysql8 InnoDB_16


修复了MySQL5.7中对于自增主键的Bug;

5.3.3、innodb_autoinc_lock_mode

MySQL5.7中的值

mysql8 InnoDB mysql8 innodb增强_数据_17


MySQL8.0中的值

mysql8 InnoDB mysql8 innodb增强_InnoDB增强_18


2代表的是交叉模式,1代表的是连续模式,也就是说再MySQL8.0中的锁是交叉生成的。

在基于语句的复制的时候会导致自增列的值不是连续的。

5.4、死锁检查控制

mysql8 InnoDB mysql8 innodb增强_数据_19

5.4.1、死锁实例演示

5.4.1.1、在innodb_deadlock_detect默认开启的模式下

在MySQL8.0中创建一个表,并在开启事务的情况下查询i=1的这条数据;

-- 会获取一个共享锁
select xxxx for share

mysql8 InnoDB mysql8 innodb增强_InnoDB增强_20


在第二个窗口中也开启一个事务;并执行删除i=1的数据的操作,可以看到,由于第一个窗口中的对id=1的数据有一个共享锁,所以这里需要等待这个共享锁的释放;

mysql8 InnoDB mysql8 innodb增强_死锁_21


回到第一个窗口执行删除i=1的数据的操作,执行成功;

mysql8 InnoDB mysql8 innodb增强_自增_22


切换到第二个窗口,发现出现死锁;

mysql8 InnoDB mysql8 innodb增强_自增_23

5.4.1.2、在innodb_deadlock_detect默认关闭的模式下

设置关闭死锁检查,为了方便测试,将死锁的等待时间从50秒设置为5秒;

mysql8 InnoDB mysql8 innodb增强_InnoDB增强_24


继续上一个的实验,可以看到在第二个窗口中出现锁等待超时而回滚;

mysql8 InnoDB mysql8 innodb增强_InnoDB增强_25


而第一个窗口中执行的delete操作由于没到锁等待超时,在第二个窗口的锁等待超时而回滚后,这里的delete操作会顺利执行。

mysql8 InnoDB mysql8 innodb增强_InnoDB增强_26

5.5、锁定语句选项

mysql8 InnoDB mysql8 innodb增强_自增_27

5.5.1、实例演示

开启一个事务,并更新一条数据,暂不提交;

mysql8 InnoDB mysql8 innodb增强_数据_28

5.5.1.1、nowait实例演示

在另一个窗口中开启一个事务,并且使用nowait,在执行后马上返回错误信息;

mysql8 InnoDB mysql8 innodb增强_数据_29

5.5.1.2、skip locked实例演示

如下图,添加了skip的语句执行后会跳过加上锁的数据;就例如2这条数据在订票系统中已经被锁定了,别的客户在查询的时候是不可被查询到的。

mysql8 InnoDB mysql8 innodb增强_数据_30

5.5.2、注意点

这两个都是针对行级锁的。由于这两个参数带来的不确定性,我们在做数据复制的时候。数据库主从节点运行的环境可能不一样,会导致备份可能会被跳过行数。导致主从数据库数据不一致。

5.6、其他改进功能

mysql8 InnoDB mysql8 innodb增强_mysql8 InnoDB_31


mysql8 InnoDB mysql8 innodb增强_InnoDB增强_32


mysql8 InnoDB mysql8 innodb增强_自增_33