MySQL中一个文档疏漏的分析测试(r13笔记第3天)

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 最近看到Percona的工程师Agustín写了一篇博客,是关于MySQL触发器和可更新视图的一个观点,具体链接可以参考 https://www.percona.

最近看到Percona的工程师Agustín写了一篇博客,是关于MySQL触发器和可更新视图的一个观点,具体链接可以参考 https://www.percona.com/blog/2017/06/14/triggers-and-updatable-views/

 

官方文档对于触发器的基本描述是这样的:


Important: MySQL triggers activate only for changes made to tables by SQL statements. They do not activate for changes in views, nor by changes to tables made by APIs that do not transmit SQL statements to the MySQL server.

 大体的翻译就是:MySQL触发器仅由SQL语句对表级触发,视图不可以,API级别的表级操作也不会触发。


这个描述看起来没什么问题,毕竟触发器是确实存在于具体的表上的,由表来触发听起来无可厚非。但是Agustín认为官方文档的描述不够严谨,而且主动提交了一个bug给官方,当然他这么说,一来是对这方面的内容有深入的理解,而另外一方面是他做了大量的测试,涵盖了MySQL 5.5, 5.6, 5.7.18(目前最新的版本),所以就事论事,这是一种很专业,严谨的态度。

 

Agustín测试的步骤如下:

他创建了一个测试表main_table,一个信息记录表 table_trigger_control,一个视图view_main_table.

当然我也按捺不住,自己也测试一把,当然我是在在他的基础上做了调整,适当简化了下测试过程。

我们创建一个两个表,一个是基表,一个是记录表,一个是视图。

基表

CREATE TABLE `main_table` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `letters` varchar(64) DEFAULT NULL,
    `numbers` int(11) NOT NULL,
    `time` time NOT NULL,
    PRIMARY KEY (`id`)
  ) ENGINE=InnoDB ;

控制表
CREATE TABLE `table_trigger_control` (
      `id` int(11),
      `description` varchar(255)
    ) ENGINE=InnoDB  ;视图
 CREATE VIEW view_main_table AS SELECT * FROM main_table;
然后创建3个触发器,分别对应insert,update,delete操作

CREATE TRIGGER trigger_after_insert after INSERT ON main_table FOR EACH ROW
    INSERT INTO table_trigger_control VALUES (NEW.id, "AFTER INSERT");
create trigger trigger_after_update after update on main_table for each row
     insert into table_trigger_control values(new.id,'AFTER UPDATE');    
     
create trigger trigger_after_delete after delete on main_table for each row
     insert into table_trigger_control values(old.id,'AFTER DELETE');  
测试的场景相对比较简单,就是测试DML的几个场景即可,比如:
1)insert 3行数据
2)update 第2行
3)delete 第3行

具体的语句如下:

 INSERT INTO main_table VALUES (1, 'A', 10, time(NOW()));
 INSERT INTO main_table VALUES (2, 'B', 20, time(NOW()));
 INSERT INTO main_table VALUES (3, 'C', 30, time(NOW()));
 UPDATE main_table SET letters = 'MOD' WHERE id = 2;
 DELETE FROM main_table WHERE id = 3;测试之后,我们来看看最后的结果:

 select *from main_table;
+----+---------+---------+----------+
| id | letters | numbers | time     |
+----+---------+---------+----------+
|  1 | A       |      10 | 23:03:09 |
|  2 | MOD     |      20 | 23:03:13 |
+----+---------+---------+----------+ 而触发器触发后的信息记录在table_trigger_control里面。

> SELECT * FROM table_trigger_control;
+------+--------------+
| id   | description  |
+------+--------------+
|    1 | AFTER INSERT |
|    2 | AFTER INSERT |
|    3 | AFTER INSERT |
|    2 | AFTER UPDATE |
|    3 | AFTER DELETE |
+------+--------------+
5 rows in set (0.00 sec)3个Insert,1个update,1个delete,刚好是5个。
这里看起来没有什么特别的,我们来看看视图的情况,也是这里测试的一个关键。

具体的语句如下:

INSERT INTO view_main_table VALUES (4, 'VIEW_D', 40, time(NOW()));
INSERT INTO view_main_table VALUES (5, 'VIEW_E', 50, time(NOW()));
INSERT INTO view_main_table VALUES (6, 'VIEW_F', 60, time(NOW()));
UPDATE view_main_table SET letters = 'VIEW_MOD' WHERE id = 5;
DELETE FROM view_main_table WHERE id = 6;

语句运行后的结果如下:

[test]>  select *from main_table;
+----+----------+---------+----------+
| id | letters  | numbers | time     |
+----+----------+---------+----------+
|  1 | A        |      10 | 23:03:09 |
|  2 | MOD      |      20 | 23:03:13 |
|  4 | VIEW_D   |      40 | 23:04:43 |
|  5 | VIEW_MOD |      50 | 23:04:46 |
+----+----------+---------+----------+
4 rows in set (0.00 sec)而触发器触发后的信息记录表内容如下:
> SELECT * FROM table_trigger_control;
+------+--------------+
| id   | description  |
+------+--------------+
|    1 | AFTER INSERT |
|    2 | AFTER INSERT |
|    3 | AFTER INSERT |
|    2 | AFTER UPDATE |
|    3 | AFTER DELETE |
|    4 | AFTER INSERT |
|    5 | AFTER INSERT |
|    6 | AFTER INSERT |
|    5 | AFTER UPDATE |
|    6 | AFTER DELETE |
+------+--------------+
10 rows in set (0.00 sec)由此看来,也是成功触发了5次。

这么看来和表的效果一样啊。

我们换一个姿势,创建一个新的视图:

> CREATE ALGORITHM=TEMPTABLE VIEW view_main_table_temp AS SELECT * FROM main_table;

然后继续插入一条记录,结果就报错了。

> INSERT INTO view_main_table_temp VALUES (7, 'VIEW_H', 70, time(NOW()));
ERROR 1471 (HY000): The target table view_main_table_temp of the INSERT is not insertable-into这个时候不确定before insert的触发器触发了吗,可以再补充一个触发器。

CREATE TRIGGER trigger_before_insert BEFORE INSERT ON main_table FOR EACH ROW
    INSERT INTO table_trigger_control VALUES (NEW.id, "BEFORE INSERT");继续尝试,还是失败。   

> INSERT INTO view_main_table_temp VALUES (7, 'VIEW_H', 70, time(NOW()));
ERROR 1471 (HY000): The target table view_main_table_temp of the INSERT is not insertable-into查看触发器控制信息表,会发现没有任何新增的记录,可见这种类型的视图是不会成功触发的。

> select *from table_trigger_control;
+------+--------------+
| id   | description  |
+------+--------------+
|    1 | AFTER INSERT |
|    2 | AFTER INSERT |
|    3 | AFTER INSERT |
|    2 | AFTER UPDATE |
|    3 | AFTER DELETE |
|    4 | AFTER INSERT |
|    5 | AFTER INSERT |
|    6 | AFTER INSERT |
|    5 | AFTER UPDATE |
|    6 | AFTER DELETE |
+------+--------------+
10 rows in set (0.00 sec)当然不光insert,update和delete也是一样的效果。

 UPDATE view_main_table_temp SET letters = 'VIEW_MOD' WHERE id = 5;
 DELETE FROM view_main_table_temp WHERE id = 5;这方面Agustín特别提出了,在这方面MariaDB的文档表述就值得赞了。
 https://mariadb.com/kb/en/mariadb/trigger-limitations/
 当然官方的态度也是值得认可的,很快就确认了这个bug,将会马上更新。

所以说,为社区共享也有很多种方式,对技术保持好奇心是学习进步的永恒动力。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
16天前
|
关系型数据库 MySQL 索引
mysql 分析5语句的优化--索引添加删除
mysql 分析5语句的优化--索引添加删除
12 0
|
21天前
|
人工智能 搜索推荐 Serverless
使用金庸的著作,来测试阿里通义千问最新开放的长文档处理功能
使用金庸的著作,来测试阿里通义千问最新开放的长文档处理功能
50 7
使用金庸的著作,来测试阿里通义千问最新开放的长文档处理功能
|
1月前
Mybatis+mysql动态分页查询数据案例——测试类HouseDaoMybatisImplTest)
Mybatis+mysql动态分页查询数据案例——测试类HouseDaoMybatisImplTest)
21 1
|
27天前
|
SQL 关系型数据库 MySQL
【MySQL技术专题】「问题实战系列」深入探索和分析MySQL数据库的数据备份和恢复实战开发指南(8.0版本升级篇)
【MySQL技术专题】「问题实战系列」深入探索和分析MySQL数据库的数据备份和恢复实战开发指南(8.0版本升级篇)
96 0
|
16天前
|
SQL 缓存 关系型数据库
mysql性能优化-慢查询分析、优化索引和配置
mysql性能优化-慢查询分析、优化索引和配置
82 1
|
22天前
|
缓存 关系型数据库 MySQL
MySQL 查询优化:提速查询效率的13大秘籍(索引设计、查询优化、缓存策略、子查询优化以及定期表分析和优化)(中)
MySQL 查询优化:提速查询效率的13大秘籍(索引设计、查询优化、缓存策略、子查询优化以及定期表分析和优化)(中)
|
2天前
|
测试技术 数据安全/隐私保护
深入理解与应用软件测试中的边界值分析法
【4月更文挑战第23天】在软件测试的诸多技术中,边界值分析法因其简洁性和高效性而备受青睐。本文旨在探讨边界值分析法的核心原理及其在实际测试场景中的应用。通过对边界条件进行系统的识别、分类和测试,该方法能够有效地发现软件缺陷。我们将详细讨论如何确定边界值,设计测试用例,以及如何处理复杂数据类型的边界情况。此外,文章还将展示通过案例研究来验证边界值分析法在提升测试覆盖率和发现潜在错误方面的实际效益。
|
2天前
|
关系型数据库 MySQL 中间件
【MySQL实战笔记】07 | 行锁功过:怎么减少行锁对性能的影响?-02 死锁和死锁检测
【4月更文挑战第19天】在高并发环境下,死锁发生在多个线程间循环等待资源时,导致无限期等待。MySQL中,死锁可通过`innodb_lock_wait_timeout`参数设置超时或`innodb_deadlock_detect`开启死锁检测来解决。默认的50s超时可能不适用于在线服务,而频繁检测会消耗大量CPU。应对热点行更新引发的性能问题,可以暂时关闭死锁检测(风险是产生大量超时),控制并发度,或通过分散记录减少锁冲突,例如将数据分拆到多行以降低死锁概率。
18 1
|
7天前
R语言估计多元标记的潜过程混合效应模型(lcmm)分析心理测试的认知过程
R语言估计多元标记的潜过程混合效应模型(lcmm)分析心理测试的认知过程
30 0
|
12天前
|
存储 关系型数据库 MySQL
【MySQL实战笔记】 04 | 深入浅出索引(上)-02
【4月更文挑战第9天】InnoDB数据库使用B+树作为索引模型,其中主键索引的叶子节点存储完整行数据,非主键索引则存储主键值。主键查询只需搜索一棵树,而非主键查询需两次搜索,因此推荐使用主键查询以提高效率。在插入新值时,B+树需要维护有序性,可能导致数据页分裂影响性能。自增主键在插入时可避免数据挪动和页分裂,且占用存储空间小,通常更为理想。然而,如果场景仅需唯一索引,可直接设为主键以减少查询步骤。
15 1
【MySQL实战笔记】 04 | 深入浅出索引(上)-02

热门文章

最新文章