Wednesday, October 11, 2006

Catch-22 of the Active Database

People frequently ask if they can do fancy things in triggers, such as writing to the filesystem, sending an email, or notifying other applications of data changes.

I always recommend against doing things like this. Calling an external processes from a trigger or UDF is very difficult to get right, and it is very easy to cause serious problems with your application.

Say for instance that you want to send an email from within a trigger, to notify someone of a data change.

An operation that spawned the trigger may be rolled back, or it may fail for another reason (violated a constraint, etc.). But the call out to the external process occurs anyway. So the email is sent, but then the database change turns out not to be committed. Thus someone has been notified of a change that effectively hasn't happened.

Even if the operation is successful, it may not be committed immediately. But triggers fire at the time of the operation, not the time of the commit. So the email could be received and the recipient goes to look for the new data. They might not find it, because it's still pending a commit.

It's better to perform notifications to external processes in your application code. After you have confirmed that the database change happened successfully, and the transaction was committed, you can notify other external applications directly.

This doesn't quite work for secondary operations, though. For instance, your app does an UPDATE, and the update trigger does another SQL operation, like INSERT. That INSERT operation is the one about which you want to notify some person or application. How can the application know that the INSERT was successful? How can your app know the values that were inserted, so that it can include those in the notification?

Another similar example is if your app does an operation which affects other data via a foreign key declared with cascading referential integrity rules. For instance, your app does a DELETE, and a dependent table which refers to that table cascades the delete. The deletes on the dependent table are the changes about which you want to notify some person or application. How does the calling application know which tables were affected by cascading operations?

I don't have answers to these latter problems yet. But in most cases, your application does know the tables and rows on which it operates. In those cases, the application should generate notification events or perform other actions outside the database.

1 comment:

Cheffo said...

I think triggers *are* the answer for things such cascading deletes.

Cascading deletes, much like triggers, are means for DBAs to perform activity unrelated to applications. Ideally, application developer may be unaware of what happens after data get inserted or deleted. Honestly, I can see no reason for this beyound rising mortality rates among developers. But anyway, if somebody have valid reasons to move around data behind the scenes and developers, she deserves also means to send this proverbial mail.