Mysql 计算自动增量离其最大值有多近的简单方法?

Mysql 计算自动增量离其最大值有多近的简单方法?,mysql,auto-increment,Mysql,Auto Increment,昨天我们有一个表,它有一个smallint的自动增量PK,达到了它的最大值。我们不得不在紧急情况下改变桌子,这绝对不是我们喜欢的方式 有没有一种简单的方法来报告我们使用的每个自动增量字段接近其最大值的程度?我能想到的最好方法是执行一个showcreatetable语句,解析出自动递增列的大小,然后将其与表的自动递增值进行比较 另一方面,鉴于模式不会经常更改,我是否应该存储关于列的最大值的信息,并使用SHOW TABLE STATUS获取当前的自动增量?只需将其设为int unsigned,并永远

昨天我们有一个表,它有一个smallint的自动增量PK,达到了它的最大值。我们不得不在紧急情况下改变桌子,这绝对不是我们喜欢的方式

有没有一种简单的方法来报告我们使用的每个自动增量字段接近其最大值的程度?我能想到的最好方法是执行一个
showcreatetable
语句,解析出自动递增列的大小,然后将其与表的自动递增值进行比较


另一方面,鉴于模式不会经常更改,我是否应该存储关于列的最大值的信息,并使用SHOW TABLE STATUS获取当前的自动增量?

只需将其设为int unsigned,并永远忘记其值。

我能够找到的一个解决方案是使用advisor

advisor监视数据库中对模式、内存使用、性能等的任何更改

但它也允许您
构建定制规则,以满足特定MySQL环境的需要
。本质上,你可以创建一个你自己的监控顾问,我注意到有人在这样做,但没有解释如何创建。因此,当您的限制即将达到时,您可以发出警告

达到限制的一个解决方案可能是创建另一个具有第二个ID的列,使PK成为一个复合主键,有效地扩展您拥有的ID数量,而无需更改数据类型

例:

添加第二个PK ID字段,名为“Whatever”

假设您的限制是在自动递增下添加1024行,在第一列达到其限制后,第二列自动递增,将第一列重置为1,第二列跳转为2

1023 1
1024 1
1    2
2    2
etc.
需要在其他表中进行引用,但不需要处理数据类型。到目前为止,这并不是解决这个问题的最佳方案,您可能已经想到了更好的解决方案,但我想我可能会添加它,以防它让您想到另一个解决方案

无论采用哪种方式,无论您决定修复/监控达到的限制,都应该规划并创建另一个数据库。监视器或其他字段,或者不管您如何匆忙地修复数据库,对于手头的实际问题来说只是一个创可贴,因为如果您有其他类似的字段,并且限制很小,那么您不希望在多个字段决定同时达到其限制的那一天被卡住


希望这能有所帮助。

我觉得你的问题非常合理。您应该能够从信息模式中获取每个表的当前自动增量值。我不认为各种int类型的max值在MySQL中可以作为常量使用,但Roland Bouman演示了一种在MySQL中生成它们的简单方法:

如果将该数据放入一个表中,则可以编写一个SQL查询来获取所有表的当前自动增量状态,这样就可以看到值即将用完

下面是一个快速而肮脏的示例,让您开始学习:

create temporary table max_int_values
(
int_type varchar(10) not null,
extra varchar(8) not null default '',
max_value bigint unsigned not null,
primary key (int_type,max_value),
key int_type (int_type),
key max_value (max_value)
);

insert into max_int_values(int_type,extra,max_value) values ('tinyint','',~0 >> 57);
insert into max_int_values(int_type,extra,max_value) values ('tinyint','unsigned',~0 >> 56);
insert into max_int_values(int_type,extra,max_value) values ('smallint','',~0 >> 49);
insert into max_int_values(int_type,extra,max_value) values ('smallint','unsigned',~0 >> 48);
insert into max_int_values(int_type,extra,max_value) values ('mediumint','',~0 >> 41);
insert into max_int_values(int_type,extra,max_value) values ('mediumint','unsigned',~0 >> 40);
insert into max_int_values(int_type,extra,max_value) values ('int','',~0 >> 33);
insert into max_int_values(int_type,extra,max_value) values ('int','unsigned',~0 >> 32);
insert into max_int_values(int_type,extra,max_value) values ('bigint','',~0 >> 1);
insert into max_int_values(int_type,extra,max_value) values ('bigint','unsigned',~0);

select t.table_Schema,t.table_name,c.column_name,c.column_type,
  t.auto_increment,m.max_value,
  round((t.auto_increment/m.max_value)*100,2) as pct_of_values_used,
  m.max_value - t.auto_increment as values_left
from information_schema.tables t
  inner join information_schema.columns c 
    on c.table_Schema = t.table_Schema and c.table_name = t.table_name
  inner join max_int_values m 
    on m.int_type = substr(c.column_type,1,length(m.int_type)) 
    and ((m.extra like '%unsigned') = (c.column_type like '%unsigned'))
where c.extra = 'auto_increment'
order by pct_of_values_used;
,这里是一个用于检查自动增量容量的查询:

SELECT
  TABLE_SCHEMA,
  TABLE_NAME,
  COLUMN_NAME,
  DATA_TYPE,
  COLUMN_TYPE,
  IF(
    LOCATE('unsigned', COLUMN_TYPE) > 0,
    1,
    0
  ) AS IS_UNSIGNED,
  (
    CASE DATA_TYPE
      WHEN 'tinyint' THEN 255
      WHEN 'smallint' THEN 65535
      WHEN 'mediumint' THEN 16777215
      WHEN 'int' THEN 4294967295
      WHEN 'bigint' THEN 18446744073709551615
    END >> IF(LOCATE('unsigned', COLUMN_TYPE) > 0, 0, 1)
  ) AS MAX_VALUE,
  AUTO_INCREMENT,
  AUTO_INCREMENT / (
    CASE DATA_TYPE
      WHEN 'tinyint' THEN 255
      WHEN 'smallint' THEN 65535
      WHEN 'mediumint' THEN 16777215
      WHEN 'int' THEN 4294967295
      WHEN 'bigint' THEN 18446744073709551615
    END >> IF(LOCATE('unsigned', COLUMN_TYPE) > 0, 0, 1)
  ) AS AUTO_INCREMENT_RATIO
FROM
  INFORMATION_SCHEMA.COLUMNS
  INNER JOIN INFORMATION_SCHEMA.TABLES USING (TABLE_SCHEMA, TABLE_NAME)
WHERE
  TABLE_SCHEMA NOT IN ('mysql', 'INFORMATION_SCHEMA', 'performance_schema')
  AND EXTRA='auto_increment'
;

当然,您可以通过自动增加比率DESC来添加
订单,可能还有
限制
,以便轻松地选择最接近其限制的订单。

为什么要用小整数设置数据库?是否重新使用已从表中删除的PK?如果删除pk字段,如何保持数据完整性?我之所以这么问,是因为重新创建一个新数据库,允许为其分配更多内存,还是只临时存储数据,然后在不再使用时将其删除(如临时存储)。这是一种旧的数据模型,是在人们比现在更关心磁盘空间时创建的。数据模型的可塑性不如我所希望的。数据模型有什么问题?不允许使用alter table查询?或者什么?我注意到这里的大多数人从不让auto inc列“unsigned”-一个负的ID值对我来说是愚蠢的。。。我总是有未签名的ID列,实际上我的ID空间增加了一倍。因为磁盘空间很便宜,所以我也把它们做得更大。请参阅我上面关于我们为什么反对数据模型更改的评论。这对于我的特殊需要来说是一种过分的做法,但看起来是一种很好的通用解决方案。@David:你为什么认为这是过分的?我认为这正是你所要求的。对于“我的特殊需要”来说,这太过分了。就一般情况而言,这确实是我所要求的。