数据库触发器详解(5)
来源:未知 责任编辑:责任编辑 发表时间:2014-05-20 18:34 点击:次
after update
ON FC_Word.planinfo FOR EACH ROW
BEGIN
insert into FC_Output.abc (planid) values (New.planid);
END
|
2)查看:mysql> select showprob from planinfo where planid=1;
+----------+
| showprob |
+----------+
| 2 |
+----------+
3)执行sql:
update planinfo set showprob=200 where planid=1;触发触发器程序;
4)由于不存在FC_Output.abc,after触发器执行失败,提示:
ERROR 1146 (42S02): Table 'FC_Output.abc' doesn't exist
5)再次查看:
mysql> select showprob from planinfo where planid=1;
+----------+
| showprob |
+----------+
| 2 |
+----------+
即修改sql未执行成功。即如果after触发器执行失败,sql会回滚。
这里需要说明一下,上述实验所使用的mysql引擎是innodb,innodb引擎也是目前线上凤巢系统、北斗系统以及哥伦布系统所使用的引擎,在innodb上所建立的表是事务性表,也就是事务安全的。“对于事务性表,如果触发程序失败(以及由此导致的整个语句的失败),该语句所执行的所有更改将回滚。对于非事务性表,不能执行这类回滚”(摘自mysql使用手册)。因而,即使语句失败,失败之前所作的任何更改依然有效,也就是说,对于innodb引擎上的数据表,如果触发器中的sql或引发触发器的sql执行失效,则事务回滚,所有操作会失效。
3.4 mysql触发器程序执行的顺序
当一个表既有before类型的触发器,又有after类型的触发器时;当一条sql语句涉及多个表的update时,sql、触发器的执行顺序经过mysql源码包装过,有时比较复杂。
可以先看一段mysql的源代码,当SQL中update多表的时候,Mysql的执行过程如下(省去了无关代码):
/* 遍历要更新的所有表*/
for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local)
{
org_updated = updated
/* 如果有BEFORE 触发器,则执行;如果执行失败,跳到err2位置*/
if (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,TRG_ACTION_BEFORE, TRUE))
goto err2;
/*执行更新,如果更新失败,跳到err位置*/
if(local_error=table->file->update_row(table->record[1], table->record[0])))
goto err;
updated++; // 更新计数器
/* 如果有AFTER 触发器,则执行;如果执行失败,跳到err2位置*/
if (table->triggers &&
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, TRG_ACTION_AFTER, TRUE))
goto err2;
err:
{
/*标志错误信息,写日志等*/
}
err2:
{
/*恢复执行过的操作*/
check_opt_it.rewind();
/*如果执行了更新,且表是有事务的,做标志*/
if (updated != org_updated)
{
if (table->file->has_transactions())
transactional_tables= 1;
}
}
}
从上面代码可以找到本章开始时抛出问题的答案。
1) 如果before型触发器执行失败,直接goto跳到err2位置,不会执行后续sql语句;
相关新闻>>
最新推荐更多>>>
- 发表评论
-
- 最新评论 更多>>