当前位置: 首页 > news >正文

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

最近看到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,将会马上更新。

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

相关文章:

  • 使用swoole websocket 实现执行console php文件 把输出返回给浏览器
  • 复习
  • 初识activiti
  • canves 画视频
  • CentOS6.8安装mongodb3.0与备份脚本
  • C++传递不定参函数
  • Android笔记之网络状态推断
  • mysql 5.6.25编译安装详细步骤
  • 手写 jQuery 框架
  • P1120 小木棍 [数据加强版]
  • Oracle 11gR2 List-Range分区实验
  • python操作excel
  • 一行命令搞定node.js升级
  • 仿射梯度
  • Snapchat发布不到2个月的故事搜索功能,又双叒被Instagram抄袭了
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • Docker下部署自己的LNMP工作环境
  • es6
  • HashMap ConcurrentHashMap
  • java 多线程基础, 我觉得还是有必要看看的
  • js面向对象
  • LeetCode算法系列_0891_子序列宽度之和
  • node.js
  • SQLServer之索引简介
  • Traffic-Sign Detection and Classification in the Wild 论文笔记
  • 表单中readonly的input等标签,禁止光标进入(focus)的几种方式
  • 猴子数据域名防封接口降低小说被封的风险
  • 码农张的Bug人生 - 见面之礼
  • 携程小程序初体验
  • 译有关态射的一切
  • Hibernate主键生成策略及选择
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • 智能情侣枕Pillow Talk,倾听彼此的心跳
  • # 深度解析 Socket 与 WebSocket:原理、区别与应用
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • (23)Linux的软硬连接
  • (Note)C++中的继承方式
  • (阿里云万网)-域名注册购买实名流程
  • (附源码)计算机毕业设计SSM在线影视购票系统
  • (十六)串口UART
  • .java 9 找不到符号_java找不到符号
  • .NET Core工程编译事件$(TargetDir)变量为空引发的思考
  • .net6 webapi log4net完整配置使用流程
  • .net安装_还在用第三方安装.NET?Win10自带.NET3.5安装
  • .NET命名规范和开发约定
  • .NET企业级应用架构设计系列之应用服务器
  • .one4-V-XXXXXXXX勒索病毒数据怎么处理|数据解密恢复
  • [145] 二叉树的后序遍历 js
  • [Android] Amazon 的 android 音视频开发文档
  • [Arduino学习] ESP8266读取DHT11数字温湿度传感器数据
  • [bbk5179]第66集 第7章 - 数据库的维护 03
  • [Big Data - Kafka] kafka学习笔记:知识点整理
  • [CDOJ 838]母仪天下 【线段树手速练习 15分钟内敲完算合格】
  • [linux] GFLOPS和TFLOPS的换算
  • [MYSQL数据库]- 索引