第五章 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、集成数据字典
5.2、原子DDL操作
5.2.1、操作原子性实例
在MySQL5.7上测试操作,从下图中可见,我们在执行删除两张表的时候虽然报错,但是还是删除了t1表。
在MySQL8.0上测试;可以看到drop语句报错,查看数据库中的表发现t1并没有被删除;drop操作具有原子性;
5.3、自增列持久化
5.3.1、在MySQL5.7中重现自增重复问题
创建测试表t,并添加三条测试数据;
然后我们删除掉id为3的数据,此时计数器应该为4,也就是下一条生成的数据的id应该为4;然后我们退出MySQL服务,然后重启MySQL服务;
重新登陆MySQL后,再次插入一条数据,可以发现新插入的数据的id为3;也就是说MySQL5.7中当服务重启的时候,会将计数器的值设置为当前表中的自增字段最大值+1;
此时,如果把c1字段为a的id的值改为5之后,如果我们再进行插入操作的情况下,那么就会出现主键冲突;(PS:感觉修改数据的主键的值的场景还没有在实际项目中发生过)
5.3.2、在MySQL8.0的自增的处理方式
在MySQL8.0中重复之前的操作,在删除了id为3的数据之后,重启了MySQL的服务之后,再进行插入操作的时候,生成的数据的id的值为4;
更新c1值为a的数据的id=5
发现并没有像再MySQL5.7中报错,而是生成了id=6的数据;
修复了MySQL5.7中对于自增主键的Bug;
5.3.3、innodb_autoinc_lock_mode
MySQL5.7中的值
MySQL8.0中的值
2代表的是交叉模式,1代表的是连续模式,也就是说再MySQL8.0中的锁是交叉生成的。
在基于语句的复制的时候会导致自增列的值不是连续的。
5.4、死锁检查控制
5.4.1、死锁实例演示
5.4.1.1、在innodb_deadlock_detect默认开启的模式下
在MySQL8.0中创建一个表,并在开启事务的情况下查询i=1的这条数据;
-- 会获取一个共享锁
select xxxx for share
在第二个窗口中也开启一个事务;并执行删除i=1的数据的操作,可以看到,由于第一个窗口中的对id=1的数据有一个共享锁,所以这里需要等待这个共享锁的释放;
回到第一个窗口执行删除i=1的数据的操作,执行成功;
切换到第二个窗口,发现出现死锁;
5.4.1.2、在innodb_deadlock_detect默认关闭的模式下
设置关闭死锁检查,为了方便测试,将死锁的等待时间从50秒设置为5秒;
继续上一个的实验,可以看到在第二个窗口中出现锁等待超时而回滚;
而第一个窗口中执行的delete操作由于没到锁等待超时,在第二个窗口的锁等待超时而回滚后,这里的delete操作会顺利执行。
5.5、锁定语句选项
5.5.1、实例演示
开启一个事务,并更新一条数据,暂不提交;
5.5.1.1、nowait实例演示
在另一个窗口中开启一个事务,并且使用nowait,在执行后马上返回错误信息;
5.5.1.2、skip locked实例演示
如下图,添加了skip的语句执行后会跳过加上锁的数据;就例如2这条数据在订票系统中已经被锁定了,别的客户在查询的时候是不可被查询到的。
5.5.2、注意点
这两个都是针对行级锁的。由于这两个参数带来的不确定性,我们在做数据复制的时候。数据库主从节点运行的环境可能不一样,会导致备份可能会被跳过行数。导致主从数据库数据不一致。
5.6、其他改进功能