MySQL定时任务event,储存过程(定时删除指定时间前90天指定表的数据)


由于一些业务需求,我们可能需要定时清除数据库一些废弃的数据,可以使用mysql的存储过程和事件来完成。
下面例子定时清除日志表tbl_base_count中指定天数前的数据
1.创建日志表tbl_base_count:
[sql]  view plain
  1. CREATE TABLE `tbl_base_count` (  
  2.   `id` int(11) NOT NULL AUTO_INCREMENT,  
  3.   `CAPTCHA` varchar(12) COLLATE utf8_bin NOT NULL,  
  4.   `PHONE` varchar(12) COLLATE utf8_bin NOT NULL,  
  5.   `SENDTIME` varchar(32) COLLATE utf8_bin NOT NULL,  
  6.   PRIMARY KEY (`id`)  
  7. ) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;  

2.创建事件e_del_tbl_base_count:
[sql]  view plain
  1. CREATE EVENT `e_del_tbl_base_count`   
  2. ON SCHEDULE EVERY 1 DAY STARTS '2013-06-23 17:33:43'   
  3. ON COMPLETION NOT PRESERVE ENABLE DO CALL p_del_count (90);  
上面代码表示从2013-07-30 17:33:43起每一天执行一次p_del_count这个存储过程,并带上参数

3.创建存储过程:
[sql]  view plain
  1. p_del_count   
  2. DELIMITER $$  
  3.   
  4. --  
  5. -- 存储过程  
  6. --  
  7. CREATE PROCEDURE `p_del_count`(IN `date_inter` INT)  
  8. BEGIN  
  9.     DELETE FROM LOG WHERE (TO_DAYS(NOW()) - TO_DAYS(FROM_UNIXTIME(SENDTIME)))>=date_inter;  
  10. END$$  
  11. DELIMITER ;  
按事件传过来的参数90,删除操作时间90天之前的数据
这样mysql就会定制每天去执行这个任务了。

4.(一)查看当前是否已开启事件计划(调度器)有3种方法:
[sql]  view plain
  1. SHOW VARIABLES LIKE 'event_scheduler';  
  2.  SELECT @@event_scheduler;  
  3.  SHOW PROCESSLIST;  
5.(二)开启事件计划(调度器)开关有4种方法:
[sql]  view plain
  1. SET GLOBAL event_scheduler = 1;  
  2. SET @@global.event_scheduler = 1;  
  3. SET GLOBAL event_scheduler = ON;  
  4. SET @@global.event_scheduler = ON;  

键值1或者ON表示开启;0或者OFF表示关闭;

6.(三)事件开启与关闭:
[sql]  view plain
  1. 开启某事件:ALTER EVENT e_del_logs ON COMPLETION PRESERVE ENABLE;  
  2. 关闭某事件:ALTER EVENT e_del_logs ON COMPLETION PRESERVE DISABLE; 
<think> 我们正在讨论MySQL中使用存储过程进行元数据管理。元数据管理包括查询、修改、维护数据库的结构信息(如、列、索引等)。存储过程可以封装复杂的SQL操作,提高效率并减少代码重复。 参考引用: [^1]:提到存储过程的优点包括执行效率和SQL代码封装。 [^2]:展示了一个简单的存储过程示例,使用SELECT INTO将结果存入变量。 [^3]:提到MySQL的灵活性,支持多种应用场景。 [^4]:展示了使用存储过程插入大量测试数据,其中使用了事务控制(autocommit=0和COMMIT)和循环。 [^5]:展示了存储过程结合事件调度器定时清理数据,并提到了使用索引提高效率。 在MySQL中,我们可以通过存储过程来执行元数据管理任务,例如: 1. 自动生成数据库文档(如结构报告) 2. 批量修改结构(如为所有添加一个公共列) 3. 监控数据库模式变化(如检查索引缺失) 4. 定期维护(如清理历史数据或优化) 下面我们将重点介绍如何使用存储过程进行元数据管理,包括查询元数据(如列出所有及其列信息)和修改元数据(如批量添加列)。 注意:在存储过程中执行动态SQL(特别是DDL语句)需要使用预处理语句(PREPARE和EXECUTE)。 步骤1:创建存储过程查询元数据 例如,创建一个存储过程,接收数据库名作为参数,输出该数据库中所有及其列的信息。 步骤2:创建存储过程修改元数据 例如,创建一个存储过程,为指定数据库中的所有添加一个相同的列(如果该列不存在)。 步骤3:使用存储过程进行维护 例如,定期清理数据(如引用[^5]所示)或重建索引。 具体示例: 示例1:查询元数据(获取所有及其列信息) 我们可以利用information_schema中的(如TABLES和COLUMNS)来获取元数据。 示例2:修改元数据(批量添加列) 注意:修改结构需要动态SQL,因为名是变量。 示例3:维护任务(清理数据) 如引用[^5]所示,我们可以创建存储过程删除过期数据,然后通过事件定时调用。 下面给出两个存储过程示例: 示例1:生成数据结构报告的存储过程存储过程将遍历指定数据库的所有,并输出每张的列信息(列名、数据类型、是否为空等)。 示例2:为所有添加一个公共列的存储过程存储过程将检查每个是否已存在该列,如果不存在则添加。 注意:在存储过程中执行DDL(ALTER TABLE)需要动态SQL。 我们开始编写存储过程: 示例1:生成结构报告的存储过程(这里我们选择将结果输出到控制台,实际也可以插入到某个中) 由于存储过程不能直接返回多结果集,我们可以先创建一个临时来存储结果,然后在存储过程外查询该,或者使用SELECT在过程中输出(但注意只能输出一个结果集)。这里我们使用SELECT输出,但注意多个SELECT会形成多个结果集,因此我们使用UNION ALL或者在一个结果集中输出(这里我们采用在一个结果集中输出,所以使用临时存储,最后再查询临时)。 然而,为了简单演示,我们可以使用游标逐查询,并将每张的列信息插入到临时中,最后一次性输出。 示例2:为所有添加公共列的存储过程 另外,注意事务:DDL语句会隐式提交,所以不能在事务中执行多个DDL(除非使用MySQL8.0的原子DDL)。因此,我们为每个单独执行ALTER,如果出错就在循环中捕获错误继续下一个。 下面给出示例代码: 示例1:生成结构报告 ```sql DELIMITER // CREATE PROCEDURE GenerateSchemaReport(IN dbName VARCHAR(64)) BEGIN -- 创建临时存储结果 DROP TEMPORARY TABLE IF EXISTS TableSchemaReport; CREATE TEMPORARY TABLE TableSchemaReport ( TableName VARCHAR(64), ColumnName VARCHAR(64), DataType VARCHAR(64), IsNullable VARCHAR(3), ColumnKey VARCHAR(3) ); -- 使用游标遍历所有 DECLARE done BOOLEAN DEFAULT FALSE; DECLARE curTable VARCHAR(64); DECLARE tableCursor CURSOR FOR SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = dbName AND TABLE_TYPE = 'BASE TABLE'; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN tableCursor; tableLoop: LOOP FETCH tableCursor INTO curTable; IF done THEN LEAVE tableLoop; END IF; -- 将当的列信息插入临时 INSERT INTO TableSchemaReport SELECT curTable, COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_KEY FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = dbName AND TABLE_NAME = curTable; END LOOP; CLOSE tableCursor; -- 输出结果 SELECT * FROM TableSchemaReport; -- 可以选择不删除临时,因为会话结束会自动删除 -- DROP TEMPORARY TABLE TableSchemaReport; END // DELIMITER ; ``` 示例2:为所有添加一个公共列(例如:添加`created_at`列,类型为TIMESTAMP) ```sql DELIMITER // CREATE PROCEDURE AddColumnToAllTables(IN dbName VARCHAR(64), IN colName VARCHAR(64), IN colType VARCHAR(64)) BEGIN DECLARE done BOOLEAN DEFAULT FALSE; DECLARE curTable VARCHAR(64); DECLARE stmt VARCHAR(1024); -- 获取所有 DECLARE tableCursor CURSOR FOR SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = dbName AND TABLE_TYPE = 'BASE TABLE'; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN tableCursor; tableLoop: LOOP FETCH tableCursor INTO curTable; IF done THEN LEAVE tableLoop; END IF; -- 检查该是否已经存在该列 IF NOT EXISTS ( SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = dbName AND TABLE_NAME = curTable AND COLUMN_NAME = colName ) THEN -- 动态构造SQL语句 SET @sql = CONCAT('ALTER TABLE `', dbName, '`.`', curTable, '` ADD COLUMN `', colName, '` ', colType); -- 预处理并执行 PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; END IF; END LOOP; CLOSE tableCursor; END // DELIMITER ; ``` 注意:在实际使用中,考虑以下事项: 1. 错误处理:上述存储过程中,如果某个执行ALTER出错,会中断整个存储过程。为了更健壮,可以单独处理每个的错误(使用DECLARE CONTINUE HANDLER FOR SQLEXCEPTION),记录错误然后继续。 2. 性能:如果很多,可能需要考虑性能影响。 3. 权限:执行存储过程需要足够的权限(如SELECT INFORMATION_SCHEMA的权限以及ALTER的权限)。 此外,存储过程也可以用于其他元数据管理任务,如: - 批量重命名列 - 删除所有的某个列 - 生成索引报告并建议添加索引 总之,使用存储过程进行元数据管理可以提高效率并减少重复工作。结合事件调度器(如引用[^5]所示),还可以实现定期自动维护。 最后,生成相关问题: </think> ### MySQL使用存储过程进行元数据管理的方法 在MySQL中,存储过程是执行元数据管理的强大工具,它能封装复杂操作、提高执行效率并减少代码冗余。以下是具体方法和示例: #### 1. **元数据查询与报告生成** 通过查询`information_schema`系统视图,可生成结构化元数据报告: ```sql DELIMITER $$ CREATE PROCEDURE GenerateSchemaReport(IN dbName VARCHAR(64)) BEGIN DECLARE done BOOLEAN DEFAULT FALSE; DECLARE tblName VARCHAR(64); DECLARE cur CURSOR FOR SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = dbName; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; CREATE TEMPORARY TABLE IF NOT EXISTS SchemaReport ( TableName VARCHAR(64), ColumnName VARCHAR(64), DataType VARCHAR(64), IsNullable VARCHAR(3) ); OPEN cur; read_loop: LOOP FETCH cur INTO tblName; IF done THEN LEAVE read_loop; END IF; INSERT INTO SchemaReport SELECT tblName, COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = dbName AND TABLE_NAME = tblName; END LOOP; CLOSE cur; SELECT * FROM SchemaReport; DROP TEMPORARY TABLE SchemaReport; END$$ DELIMITER ; ``` **调用方式**: ```sql CALL GenerateSchemaReport('your_database'); ``` 此过程生成包含名、列名、数据类型和可空性的详细报告[^1]。 #### 2. **自动化元数据维护** 存储过程可批量执行DDL操作,如为所有添加审计列: ```sql DELIMITER $$ CREATE PROCEDURE AddAuditColumns() BEGIN DECLARE tbl VARCHAR(64); DECLARE done BOOLEAN DEFAULT FALSE; DECLARE cur CURSOR FOR SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE(); DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cur; modify_loop: LOOP FETCH cur INTO tbl; IF done THEN LEAVE modify_loop; END IF; -- 动态SQL避免列重复添加 SET @sql = CONCAT( 'ALTER TABLE ', tbl, ' ADD COLUMN IF NOT EXISTS created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,', ' ADD COLUMN updated_at TIMESTAMP ON UPDATE CURRENT_TIMESTAMP' ); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; END LOOP; CLOSE cur; END$$ DELIMITER ; ``` #### 3. **元数据驱动的数据清理** 结合事件调度器实现定时维护(如引用[^5]): ```sql DELIMITER $$ CREATE PROCEDURE CleanOldData(IN retentionDays INT) BEGIN DECLARE tbl VARCHAR(64); DECLARE done BOOLEAN DEFAULT FALSE; DECLARE cur CURSOR FOR SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME LIKE 'log_%'; -- 仅处理日志 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; SET autocommit = 0; -- 关闭自动提交 START TRANSACTION; OPEN cur; clean_loop: LOOP FETCH cur INTO tbl; IF done THEN LEAVE clean_loop; END IF; SET @sql = CONCAT( 'DELETE FROM ', tbl, ' WHERE created_at < DATE_SUB(NOW(), INTERVAL ', retentionDays, ' DAY)' ); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; END LOOP; CLOSE cur; COMMIT; SET autocommit = 1; END$$ DELIMITER ; ``` **定时调用**(每日清理90数据): ```sql CREATE EVENT DailyDataClean ON SCHEDULE EVERY 1 DAY DO CALL CleanOldData(90); ``` #### 4. **元数据验证与修复** 检查缺失的主键并自动修复: ```sql DELIMITER $$ CREATE PROCEDURE CheckPrimaryKeys() BEGIN DECLARE tbl VARCHAR(64); DECLARE done BOOLEAN DEFAULT FALSE; DECLARE cur CURSOR FOR SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_TYPE = 'BASE TABLE'; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; CREATE TEMPORARY TABLE MissingPK ( TableName VARCHAR(64) PRIMARY KEY, Status VARCHAR(20) ); OPEN cur; check_loop: LOOP FETCH cur INTO tbl; IF done THEN LEAVE check_loop; END IF; -- 检查是否存在主键 IF NOT EXISTS ( SELECT 1 FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = tbl AND INDEX_NAME = 'PRIMARY' ) THEN INSERT INTO MissingPK VALUES (tbl, 'Missing PK'); SET @sql = CONCAT('ALTER TABLE ', tbl, ' ADD COLUMN id INT AUTO_INCREMENT PRIMARY KEY'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; END IF; END LOOP; CLOSE cur; SELECT * FROM MissingPK; -- 输出修复报告 DROP TEMPORARY TABLE MissingPK; END$$ DELIMITER ; ``` ### 关键优势与注意事项 1. **事务控制** 使用`SET autocommit=0`和显式`COMMIT`确保元数据操作的原子性(如引用[^4]所示)。 2. **动态SQL** 通过`PREPARE/EXECUTE`执行动态生成的DDL语句,解决名参数化问题。 3. **性能优化** - 游标处理大量时,限制结果集范围(如`TABLE_NAME LIKE 'log_%'`) - 索引验证:引用`information_schema.STATISTICS`优化索引管理(如引用[^5]) 4. **权限要求** 执行存储过程需`ALTER ROUTINE`权限,修改元数据需`ALTER`权限。 > **提示**:复杂元数据操作建议在低峰期执行,避免锁影响业务[^3][^5]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值