Pergunta

I want to ask your opinion in using MySQL triggers or transactions in a website.

Actually I have a history payment table with - UserId | OperationId | Comment | Credits | Sign (debit or credit). So each payment operation is inserted in this table.

However, it will be time consuming calculating each time the total credit amount of the user every time he do action. So I thought maybe is a good idea to keep the total credit amount for each user in a user profile table.

Here is the problem. How can I be sure that the total credit amount form the profile table will stay synchronized with the operations from payment history table ?

I thought using 2 methods:

  • MySQL triggers or
  • transactions coded in the source code

Which is more reliable? What if I have large database (over 100.000 users) ?

Do you have any suggestions to do this?

The BD MySQL engine is InnoDB.

Foi útil?

Solução

Without a doubt, I would rule out triggers and strictly stay with transactions.

Triggers are, by nature, stored procedures. Their actions are virtually hard to roll back. Even if all underlying tables are InnoDB, you will experience a proportional volume of shared row locks and annoying intermittency from exclusive row locks. Such would be the case if triggers were manipulating tables with INSERTs and UPDATEs being stagnated to perform heavy duty MVCC inside each call to a trigger.

Combine this with the fact that proper data validation protocols are not implemented in MySQL's Stored Procedure Language. Business Intelligence is OK to have contained in a database provided the Stored Procedure Language can handle a transactional environment. As a MySQL DBA, I have to honestly say that such is not the case with MySQL. Oracle (PL/SQL), PostgreSQL (PL/pgSQL), and SQL Server (T-SQL) have this edge over MySQL.

Concerning transactions, MySQL has InnoDB as its main ACID-compliant storage engine (Deafult storage engine in MySQL 5.5). It has excellent crash recovery and obeys the ACID compliance protocols.

I would choose transacitons over triggers every single time.

Outras dicas

I agree with Rolando's assessment. Your business logic should reside in your application and should make changes to the database transactionally.

Scaling to 100,000 users, of course, depends on your application and the database traffic it generates. With MySQL under a heavy transactional write load, you might be soon faced with the burdens of sharding and/or replicating your dataset in order to maintain acceptable application response.

However, there are alternatives to sharding MySQL. One of them is Clustrix (my employer) which is a parallel-scalable high-performance single-instance SQL database system. It's a clustered database system that presents itself as a single MySQL server. Scaling the database described in this thread seamlessly to 100,000 users on a single instance of Clustrix would require no sharding and no additional application logic.

Good answer from Rolando.

In addition -- Triggers should not be used for logic, because a couple of inter-relating triggers later, things will get confusing fast. A nice set of instructions in a stored procedure or client side procedure can get across the business logic more clearly than a bunch of hidden logic in the database. There are also limitations on triggers with respect to the table they get triggered from -- so you may find yourself splitting your logic in two different places..

In addition -- you might find ways to optimize at what point these calculations happen in your business logic server, whereas a trigger is gonna trigger every single time. You'll find yourself turning off the trigger, updating the table, and then re-enabling the trigger -- which also means you need to put the trigger logic in that code.

In addition -- you don't have to have all the logic in the business logic part of the code -- you might want to enforce the table integrity by using stored procedures. This can start a transaction, do your multiple updates, and have things roll back nicely if something fails. That way someone looking at the database can see the logic for inserting an order, for example. This is less important in today's world since web services can be the single access interface to the db; but in the case where multiple executables have access to the DB this can be huge.

In addition -- you are gonna have transactions anyway -- you're not gonna execute your triggers without one... right? So it is good to know how to start a transaction; do some stuff; and then end a transaction. If you see this pattern in your code, one more piece of code that uses it will be light on the cognitive load. A trigger, if you remember that it is there, will force you to think differently for those transactions that are affected by the trigger, especially if other tables are pulled in that also may have triggers.

Basically, between a regularly scheduled cron job (or database agent job) and good stored procedures, you can accomplish 99% of what you want. The 1%; rethink the project.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a dba.stackexchange
scroll top