1. 首页 > MariaDB教程 > 正文

MariaDB教程FG058-MariaDB触发器与事件管理实战

内容简介:本文主要介绍MariaDB触发器与事件的管理方法与实践,包括触发器的基本概念、事件的基本概念、触发器与事件的区别等内容。通过实际案例讲解触发器和事件的开发过程,帮助读者掌握触发器与事件管理的技能。风哥教程参考MariaDB官方文档Triggers、Events等相关内容。

Part01-基础概念与理论知识

1.1 触发器的基本概念

触发器(Trigger)是一种特殊的存储过程,它在特定的数据库操作(如INSERT、UPDATE、DELETE)发生时自动执行。触发器可以用于实现数据完整性约束、审计、日志记录等功能。

触发器的主要特点:

  • 自动执行:当特定的数据库操作发生时,触发器自动执行
  • 与表关联:触发器与特定的表关联,只在该表上的操作触发
  • 可以访问新旧数据:触发器可以访问操作前后的数据
  • 可以执行复杂逻辑:触发器可以执行复杂的业务逻辑

1.2 事件的基本概念

事件(Event)是一种定时执行的任务,它可以在指定的时间点或时间间隔自动执行。事件可以用于实现定期备份、数据清理、统计分析等功能。

事件的主要特点:

  • 定时执行:事件可以在指定的时间点或时间间隔自动执行
  • 独立运行:事件独立于用户操作,自动运行
  • 可以执行复杂逻辑:事件可以执行复杂的业务逻辑
  • 可以启用和禁用:事件可以根据需要启用或禁用

1.3 触发器与事件的区别

触发器与事件的主要区别:

  • 触发条件:触发器在特定的数据库操作(如INSERT、UPDATE、DELETE)发生时触发,而事件在指定的时间点或时间间隔触发
  • 执行方式:触发器与表关联,只在该表上的操作触发,而事件独立于表,定时执行
  • 使用场景:触发器适用于数据完整性约束、审计、日志记录等,而事件适用于定期备份、数据清理、统计分析等
更多视频教程www.fgedu.net.cn

Part02-生产环境规划与建议

2.1 触发器与事件规划

触发器与事件规划建议:

  • 业务逻辑分析:分析业务逻辑,确定哪些逻辑适合使用触发器或事件
  • 命名规范:使用有意义的名称,遵循命名规范
  • 性能评估:评估触发器和事件对性能的影响
  • 错误处理:添加错误处理逻辑,确保触发器和事件的稳定性

2.2 开发规范

开发规范建议:

  • 命名规范:使用前缀区分触发器和事件,如trg_前缀表示触发器,evt_前缀表示事件
  • 缩进规范:使用一致的缩进,提高代码可读性
  • 注释规范:添加适当的注释,解释复杂的逻辑
  • 代码风格:使用一致的代码风格,如关键字大写、变量名小写等

2.3 性能优化建议

性能优化建议:

  • 减少触发器的复杂性:触发器的逻辑应该简单,避免执行复杂的操作
  • 避免在触发器中使用事务:触发器已经在事务中执行,不需要再使用事务
  • 合理设置事件的执行时间:避免在系统负载高的时候执行事件
  • 使用索引:确保触发器和事件中使用的SQL语句能够利用索引
学习交流加群风哥微信: itpux-com

Part03-生产环境项目实施方案

3.1 触发器开发

更多学习教程公众号风哥教程itpux_com

# 触发器开发
MariaDB [(none)]> # 1. 创建INSERT触发器
DELIMITER //
CREATE TRIGGER trg_before_insert_user BEFORE INSERT ON fgedu_users
FOR EACH ROW
BEGIN
SET NEW.created_at = NOW();
SET NEW.updated_at = NOW();
END //
DELIMITER;
# 2. 创建UPDATE触发器
DELIMITER //
CREATE TRIGGER trg_before_update_user BEFORE UPDATE ON fgedu_users
FOR EACH ROW
BEGIN
SET NEW.updated_at = NOW();
END //
DELIMITER;
# 3. 创建DELETE触发器
DELIMITER //
CREATE TRIGGER trg_after_delete_user AFTER DELETE ON fgedu_users
FOR EACH ROW
BEGIN
INSERT INTO fgedu_user_logs(action, user_id, username, action_time)
VALUES(‘DELETE’, OLD.id, OLD.username, NOW());
END //
DELIMITER;
# 4. 查看触发器
SHOW TRIGGERS LIKE ‘fgedu_users’;
# 5. 删除触发器
DROP TRIGGER IF EXISTS trg_before_insert_user;

3.2 事件开发

# 事件开发
MariaDB [(none)]> # 1. 启用事件调度器
SET GLOBAL event_scheduler = ON;
# 2. 查看事件调度器状态
SHOW VARIABLES LIKE ‘event_scheduler’;
# 3. 创建事件
DELIMITER //
CREATE EVENT evt_cleanup_old_data
ON SCHEDULE EVERY 1 DAY
STARTS ‘2023-01-01 00:00:00’
DO
BEGIN
DELETE FROM fgedu_logs WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY);
END //
DELIMITER;
# 4. 创建一次性事件
DELIMITER //
CREATE EVENT evt_backup_data
ON SCHEDULE AT ‘2023-01-01 01:00:00’
DO
BEGIN
CALL sp_backup_database();
END //
DELIMITER;
# 5. 查看事件
SHOW EVENTS;
# 6. 修改事件
ALTER EVENT evt_cleanup_old_data ENABLE;
ALTER EVENT evt_cleanup_old_data DISABLE;
# 7. 删除事件
DROP EVENT IF EXISTS evt_cleanup_old_data;

3.3 管理与维护

# 管理与维护
MariaDB [(none)]> # 1. 查看触发器
SHOW TRIGGERS;
SHOW TRIGGERS LIKE ‘fgedu_%’;
# 2. 查看事件
SHOW EVENTS;
SHOW EVENTS LIKE ‘evt_%’;
# 3. 查看事件调度器状态
SHOW PROCESSLIST WHERE Command = ‘Daemon’;
# 4. 启用/禁用事件调度器
SET GLOBAL event_scheduler = ON;
SET GLOBAL event_scheduler = OFF;
# 5. 启用/禁用事件
ALTER EVENT evt_cleanup_old_data ENABLE;
ALTER EVENT evt_cleanup_old_data DISABLE;
# 6. 查看事件的详细信息
SHOW CREATE EVENT evt_cleanup_old_data;
学习交流加群风哥QQ113257174

Part04-生产案例与实战讲解

4.1 触发器开发案例

场景描述:开发一个触发器,用于记录用户操作日志。

# 创建日志表
MariaDB [(none)]> CREATE TABLE fgedu_user_logs (
id INT PRIMARY KEY AUTO_INCREMENT,
action VARCHAR(20),
user_id INT,
username VARCHAR(50),
action_time DATETIME,
details TEXT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 创建INSERT触发器
DELIMITER //
CREATE TRIGGER trg_after_insert_user AFTER INSERT ON fgedu_users
FOR EACH ROW
BEGIN
INSERT INTO fgedu_user_logs(action, user_id, username, action_time, details)
VALUES(‘INSERT’, NEW.id, NEW.username, NOW(), CONCAT(‘Created user: ‘, NEW.username));
END //
DELIMITER;
# 创建UPDATE触发器
DELIMITER //
CREATE TRIGGER trg_after_update_user AFTER UPDATE ON fgedu_users
FOR EACH ROW
BEGIN
INSERT INTO fgedu_user_logs(action, user_id, username, action_time, details)
VALUES(‘UPDATE’, NEW.id, NEW.username, NOW(), CONCAT(‘Updated user: ‘, OLD.username, ‘ -> ‘, NEW.username));
END //
DELIMITER;
# 测试触发器
INSERT INTO fgedu_users(username, email, password) VALUES(‘testuser’, ‘test@fgedu.net.cn’, ‘password123’);
UPDATE fgedu_users SET username = ‘updateduser’ WHERE username = ‘testuser’;
# 查看日志
SELECT * FROM fgedu_user_logs;

执行结果:

# 插入用户
Query OK, 1 row affected (0.00 sec)
# 更新用户
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
# 查看日志
+—-+——–+———+————-+———————+———————————–+
| id | action | user_id | username | action_time | details |
+—-+——–+———+————-+———————+———————————–+
| 1 | INSERT | 7 | testuser | 2023-01-01 10:00:00 | Created user: testuser |
| 2 | UPDATE | 7 | updateduser | 2023-01-01 10:00:00 | Updated user: testuser -> updateduser |
+—-+——–+———+————-+———————+———————————–+

4.2 事件开发案例

场景描述:开发一个事件,用于定期清理过期数据。

# 创建事件
MariaDB [(none)]> DELIMITER //
CREATE EVENT evt_cleanup_expired_data
ON SCHEDULE EVERY 1 WEEK
STARTS ‘2023-01-01 00:00:00’
DO
BEGIN
# 清理30天前的日志
DELETE FROM fgedu_logs WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY);
# 清理已完成的任务
DELETE FROM fgedu_tasks WHERE status = ‘completed’ AND completed_at < DATE_SUB(NOW(), INTERVAL 7 DAY);
# 优化表
OPTIMIZE TABLE fgedu_logs, fgedu_tasks;
END //
DELIMITER;
# 启用事件
ALTER EVENT evt_cleanup_expired_data ENABLE;
# 查看事件
SHOW EVENTS LIKE ‘evt_cleanup_expired_data’;
# 手动执行事件(用于测试)
CALL evt_cleanup_expired_data();

执行结果:

# 创建事件
Query OK, 0 rows affected (0.00 sec)
# 启用事件
Query OK, 0 rows affected (0.00 sec)
# 查看事件
+—————————-+——+—————-+———–+———————+———————+———————+—————-+———————-+———————-+——————–+
| Name | Definer | Time zone | Type | Execute at | Interval value | Interval field | Starts at | Ends at | Status | Originator |
+—————————-+——+—————-+———–+———————+———————+———————+—————-+———————-+———————-+——————–+
| evt_cleanup_expired_data | root@fgedu.localhost | SYSTEM | RECURRING | NULL | 1 | WEEK | 2023-01-01 00:00:00 | NULL | ENABLED | 1 |
+—————————-+——+—————-+———–+———————+———————+———————+—————-+———————-+———————-+——————–+

4.3 复杂业务逻辑实现案例

场景描述:开发一个触发器和事件的组合,用于实现订单状态的自动更新。

# 创建订单表
MariaDB [(none)]> CREATE TABLE fgedu_orders (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
order_no VARCHAR(50),
total_amount DECIMAL(10,2),
status VARCHAR(20),
created_at DATETIME,
updated_at DATETIME,
payment_deadline DATETIME
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# 创建触发器,设置支付截止时间
DELIMITER //
CREATE TRIGGER trg_before_insert_order BEFORE INSERT ON fgedu_orders
FOR EACH ROW
BEGIN
SET NEW.created_at = NOW();
SET NEW.updated_at = NOW();
SET NEW.payment_deadline = DATE_ADD(NOW(), INTERVAL 30 MINUTE);
END //
DELIMITER;
# 创建事件,自动取消超时未支付的订单
DELIMITER //
CREATE EVENT evt_cancel_unpaid_orders
ON SCHEDULE EVERY 5 MINUTE
STARTS ‘2023-01-01 00:00:00’
DO
BEGIN
UPDATE fgedu_orders
SET status = ‘cancelled’, updated_at = NOW()
WHERE status = ‘pending’ AND payment_deadline < NOW();
END //
DELIMITER;
# 测试
INSERT INTO fgedu_orders(user_id, order_no, total_amount, status) VALUES(1, ‘ORD20230101005’, 100.00, ‘pending’);
# 查看订单
SELECT * FROM fgedu_orders WHERE order_no = ‘ORD20230101005’;
# 模拟时间过期
UPDATE fgedu_orders SET payment_deadline = DATE_SUB(NOW(), INTERVAL 1 HOUR) WHERE order_no = ‘ORD20230101005’;
# 手动执行事件
CALL evt_cancel_unpaid_orders();
# 查看订单状态
SELECT * FROM fgedu_orders WHERE order_no = ‘ORD20230101005’;

执行结果:

# 插入订单
Query OK, 1 row affected (0.00 sec)
# 查看订单
+—-+———+—————+————–+———+———————+———————+———————+
| id | user_id | order_no | total_amount | status | created_at | updated_at | payment_deadline |
+—-+———+—————+————–+———+———————+———————+———————+
| 5 | 1 | ORD20230101005 | 100.00 | pending | 2023-01-01 10:00:00 | 2023-01-01 10:00:00 | 2023-01-01 10:30:00 |
+—-+———+—————+————–+———+———————+———————+———————+
# 模拟时间过期
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
# 手动执行事件
Query OK, 1 row affected (0.00 sec)
# 查看订单状态
+—-+———+—————+————–+———–+———————+———————+———————+
| id | user_id | order_no | total_amount | status | created_at | updated_at | payment_deadline |
+—-+———+—————+————–+———–+———————+———————+———————+
| 5 | 1 | ORD20230101005 | 100.00 | cancelled | 2023-01-01 10:00:00 | 2023-01-01 10:00:00 | 2023-01-01 09:00:00 |
+—-+———+—————+————–+———–+———————+———————+———————+
风哥提示:安全开发是防止SQL注入的第一道防线

Part05-风哥经验总结与分享

5.1 触发器与事件管理最佳实践

风哥提示:在使用触发器和事件时,应遵循最佳实践,提高代码的质量、性能和可维护性。
  • 合理使用触发器:只在必要时使用触发器,避免过度使用
  • 保持触发器逻辑简单:触发器的逻辑应该简单,避免执行复杂的操作
  • 合理设置事件的执行时间:避免在系统负载高的时候执行事件
  • 添加错误处理:使用异常处理机制,确保触发器和事件的稳定性
  • 定期维护:定期检查和优化触发器和事件,确保其性能

5.2 性能优化技巧

  • 减少触发器的数量:避免在同一个表上创建过多的触发器
  • 优化触发器中的SQL语句:确保触发器中的SQL语句能够利用索引
  • 合理设置事件的执行频率:根据业务需求设置合适的执行频率
  • 使用批处理:对于大量数据的操作,使用批处理提高性能
  • 监控事件执行情况:定期监控事件的执行情况,及时发现问题

5.3 常见问题与解决方案

  • 触发器执行失败:检查触发器中的SQL语句,确保语法正确
  • 事件不执行:检查事件调度器是否启用,事件是否启用
  • 性能问题:优化触发器和事件中的SQL语句,减少执行时间
  • 死锁:避免在触发器中执行长时间运行的操作
  • 数据一致性:确保触发器和事件的逻辑不会破坏数据一致性
# 触发器与事件管理示例
— 创建触发器
DELIMITER //
CREATE TRIGGER trg_before_insert_order BEFORE INSERT ON fgedu_orders
FOR EACH ROW
BEGIN
SET NEW.created_at = NOW();
SET NEW.updated_at = NOW();
SET NEW.payment_deadline = DATE_ADD(NOW(), INTERVAL 30 MINUTE);
END //
DELIMITER;
— 创建事件
DELIMITER //
CREATE EVENT evt_cancel_unpaid_orders
ON SCHEDULE EVERY 5 MINUTE
STARTS ‘2023-01-01 00:00:00’
DO
BEGIN
UPDATE fgedu_orders
SET status = ‘cancelled’, updated_at = NOW()
WHERE status = ‘pending’ AND payment_deadline < NOW();
END //
DELIMITER;
— 启用事件
ALTER EVENT evt_cancel_unpaid_orders ENABLE;
— 查看事件
SHOW EVENTS LIKE ‘evt_cancel_unpaid_orders’;

通过以上措施,可以有效提高MariaDB触发器与事件管理的质量和性能,确保系统稳定运行。

from MariaDB视频:www.itpux.com

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息