GreatSQL社区

搜索

chongzh

单表文件大小文件系统限制后删除部分数据仍无法插入新数据,报the table is full ...

chongzh 已有 2115 次阅读2024-5-21 08:26 |个人分类:Mysql 原理|系统分类:运维实战

环境信息
MySQL 5.7.21
文件系统 ext3

问题描述
单表idb文件达到2T(ext3文件系统单文件最大限制),当表insert时会报错 the table is full,开发紧急delete掉6万行数据后,ibd文件大小未减小,insert新数据继续报错 the table is full 。(ps:临时应急:在未改变文件系统ext3的情况下,rename 旧表,建同名新表,确保增量插入可用,并进行存量数据迁移)

应用报错截图:

错误日志报错截图:

数据清理语句:
delete语句:

DELETE FROM release WHERE AppId="120685" AND ClusterName="default" AND NamespaceName="F-HMP.CLIENT" AND id<44425775 (二次确认已删除成功了)


表结构:
CREATE TABLE `release` (

 `Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '',

 `ReleaseKey` varchar(64) CHARACTER SET utf8mb4 NOT NULL DEFAULT '' COMMENT '',

 `Name` varchar(64) CHARACTER SET utf8mb4 NOT NULL DEFAULT 'default' COMMENT '',

 `Comment` varchar(256) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '',

 `AppId` varchar(500) CHARACTER SET utf8mb4 NOT NULL DEFAULT 'default' COMMENT '',

 `ClusterName` varchar(500) CHARACTER SET utf8mb4 NOT NULL DEFAULT 'default' COMMENT '',

 `NamespaceName` varchar(500) CHARACTER SET utf8mb4 NOT NULL DEFAULT 'default' COMMENT '',

 `Configurations` longtext CHARACTER SET utf8mb4 NOT NULL COMMENT '',

 `IsAbandoned` bit(1) NOT NULL DEFAULT b'0' COMMENT '',

 `IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '',

 `DataChange_CreatedBy` varchar(32) CHARACTER SET utf8mb4 NOT NULL DEFAULT 'default' COMMENT '',

 `DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '',

 `DataChange_LastModifiedBy` varchar(32) CHARACTER SET utf8mb4 DEFAULT '' COMMENT '',

 `DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '',

 `Ucm` longtext COLLATE utf8mb4_bin COMMENT '',

 PRIMARY KEY (`Id`),

 KEY `AppId_ClusterName_GroupName` (`AppId`(191),`ClusterName`(191),`NamespaceName`(191)),

 KEY `DataChange_LastTime` (`DataChange_LastTime`),

 KEY `IX_ReleaseKey` (`ReleaseKey`)

) ENGINE=InnoDB AUTO_INCREMENT=46041420 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT=''



表ibd大小:

cmc-0018-0:/data/mysql_data/data/apolloconfigdb # ls -l release.ibd 
-rw-r----- 1 mysql mysql 2194719883264 May 13 08:55 release.ibd


疑问1: 单表idb文件达到文件系统上限后,delete 清理6万数据后,为什么仍无法执行insert操作?

一个extent 在16KB page size 的情况下是1MB,删除的行未必位于相同的extent( where 条件有很多其他的条件 说明删除不是按照主键递增做严格的范围扫描清理数据),即使innodb purge 处理过之后,仍然无法腾出完整的若干个extent,让文件系统可以复用若干16KB的空间

疑问2:单表idb文件达到文件系统上限后,有办法能直接让该表能继续新增数据吗?

按照where 条件只有自增主键做范围扫描的数据清理,Innodb可以把数据文件中全空的extent 或者page 复用起来(测试复现如下)


mysql> show create table t_user_1_1000_10000\G
*************************** 1. row ***************************
       Table: t_user_1_1000_10000
Create Table: CREATE TABLE `t_user_1_1000_10000` (
  `id` int NOT NULL AUTO_INCREMENT,
  `c_name` varchar(1000) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=40000 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
mysql>  select count(*) from t_user_1_1000_10000;
+----------+
| count(*) |
+----------+
|    30000 |
+----------+
1 row in set (0.04 sec)

mysql> select min(id),max(id) from  t_user_1_1000_10000;
+---------+---------+
| min(id) | max(id) |
+---------+---------+
|       1 |   30000 |
+---------+---------+
1 row in set (0.00 sec)

mysql> delete from t_user_1_1000_10000 where id < 10000 and id > 20000;
Query OK, 9999 rows affected (0.20 sec)

mysql> call  add_t_user_1_1000_10000(5000);
Query OK, 1 row affected (39.79 sec)

mysql> call  add_t_user_1_1000_10000(4999);
Query OK, 1 row affected (39.35 sec)

mysql> select count(*) from t_user_1_1000_10000;
+----------+
| count(*) |
+----------+
|    30000 |
+----------+
1 row in set (0.04 sec)

[root@test_greatsql_01 bbb]# du -h t_user_1_1000_10000.ibd 
45M  t_user_1_1000_10000.ibd
[root@test_greatsql_01 bbb]# 
[root@test_greatsql_01 bbb]# du -h t_user_1_1000_10000.ibd 
45M  t_user_1_1000_10000.ibd

造数脚本:
CREATE TABLE `t_user_1_1000_10000` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `c_name` varchar(1000) NOT NULL,
  PRIMARY KEY (`id`)
) CHARSET=utf8mb4;



# 创建随机字符串
delimiter $$
DROP FUNCTION IF EXISTS `randStr` $$
CREATE DEFINER=`root`@`%` FUNCTION `randStr`(n INT) RETURNS varchar(1000) CHARSET utf8mb4
    DETERMINISTIC
BEGIN
    DECLARE chars_str varchar(100) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    DECLARE return_str varchar(1000) DEFAULT '' ;
    DECLARE i INT DEFAULT 0;
    WHILE i < n DO
        SET return_str = concat(return_str, substring(chars_str, FLOOR(1 + RAND() * 62), 1));
        SET i = i + 1;
    END WHILE;
    RETURN return_str;
END$$



# 创建插入数据存储过程
delimiter $$
CREATE DEFINER=`root`@`%` PROCEDURE `add_t_user_1_1000_10000`(IN n int)
BEGIN
    DECLARE i INT DEFAULT 1;
    WHILE (i <= n) DO
        INSERT INTO t_user_1_1000_10000 (c_name) VALUES ( randStr(1000));
        SET i = i + 1;
    END WHILE;
END $$
delimiter ;



call  add_t_user_1_1000_10000(30000);



评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 立即注册

合作电话:010-64087828

社区邮箱:greatsql@greatdb.com

社区公众号
社区小助手
QQ群
GMT+8, 2024-12-21 22:04 , Processed in 0.015519 second(s), 10 queries , Redis On.
返回顶部