前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >通过shell脚本模拟MySQL自增列的不一致问题

通过shell脚本模拟MySQL自增列的不一致问题

作者头像
jeanron100
发布2018-03-21 16:56:59
1.4K0
发布2018-03-21 16:56:59
举报

MySQL的自增列问题其实很有意思,在重启数据库之后,会按照max(id)+1的方式来计算,这样一个看起来有些别扭的实现方式在早期版本就饱受诟病,在MySQL 5.7都没有解决掉,终于在8.0松口了,计划在这个版本中修复。

而重启会带来自增列一类的潜在问题,而如果不重启其实也有可能会有自增列的不一致问题。和两个参数table_definition_cache和table_open_cache还是密切相关的。

主要的原因是什么呢,引用阿里数据库内核团队的解释(https://www.kancloud.cn/taobaomysql/monthly/67171):一方面InnoDB表自增值是存储在表对象中的,表对象又是放在缓存中的,如果表太多而不能全部放在缓存中的话,老的表就会被置换出来,这种被置换出来的表下次再使用的时候,就要重新打开一遍,对自增列来说,这个过程就和实例重启类似,需要 select max(id) + 1 算一下自增值。

表对象缓存大小由 table_definition_cache 系统变量控制,最小值为400,表缓存相关的另一个系统变量是table_open_cache,这个控制的是所有线程打开表的缓存大小,这个缓存放在server层。

我在查看了5.6.14的环境之后,发现这个值已经提升到了500,而在MySQL 5.7中,提升到了1400,可见这方面了下了大功夫。

MySQL 5.6.14的参数值情况

# mysqladmin var|grep table_open_cache | table_open_cache | 256 | table_open_cache_instances | 1 # mysqladmin var|grep table_definition_cache | table_definition_cache | 500

MySQL 5.7中的参数值情况:

mysql> show variables like 'table_definition_cache'; | Variable_name | Value | | table_definition_cache | 1400 |

mysql> show variables like 'table_open_cache'; | Variable_name | Value | | table_open_cache | 2000 |

阿里的同学给出了testcase的伪代码,我就来实现以下,给出shell版本的测试脚本。

首先我们可以模拟一下这个测试的基线,把两个变量都修改为400.

SET GLOBAL table_definition_cache = 400; SET GLOBAL table_open_cache = 400;

然后使用如下的shell脚本,仔细来看,脚本逻辑很简单了。

生成500个表,然后插入一条数据,修改自增列值,然后查询表里的数据,使得数据能够刷出,稍作等待,查看show create table的结果。

for i in {1..500} do mysql test_new <<EOF CREATE TABLE t$i(id INT NOT NULL AUTO_INCREMENT, name VARCHAR(30), PRIMARY KEY(id)) ENGINE=InnoDB; INSERT INTO t$i(name) VALUES("InnoDB"); ALTER TABLE t$i AUTO_INCREMENT = 100; EOF done for i in {1..500} do mysql test_new <<EOF SELECT * FROM t$i; EOF done sleep 10; for i in {1..3} do mysql test_new <<EOF SHOW CREATE TABLE t$i; EOF done

测试完成之后,来查看自增列的值情况.

在5.6.14中效果很明显。

Table Create Table t1 CREATE TABLE `t1` (\n `id` int(11) NOT NULL AUTO_INCREMENT,\n `name` varchar(30) DEFAULT NULL,\n PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8

而在5.7中,发现这类问题竟然还复现不了了,至于是代码层级做了修复还是和其它参数有关,就需要深入一下了。

Table Create Table t1 CREATE TABLE `t1` (\n `id` int(11) NOT NULL AUTO_INCREMENT,\n `name` varchar(30) DEFAULT NULL,\n PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=100 DEFAULT CHARSET=latin1

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-07-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 杨建荣的学习笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档