简体   繁体   中英

Is there any way to commit part of a transaction?

There is a function A, which starts a transaction, does some work, then calls function B, does some more work, and commits the transaction. A also catches any exceptions, which trigger a rollback instead of commit.

My problem is, that if B encounters an error, I want to record that error to my database and then prevent the transaction in A from committing. Is there any way to do that? I can't just have B call rollback, because B might be used by other functions than A, which may handle exceptions differently. So B still needs to throw the exception, which triggers the rollback. However, that wipes out the database log entry that I just created. So, is there any way to have a function commit a single insert in the middle of a transaction, while allowing the rest of the transaction to be rolled back?

For reference: I'm doing this in PHP with Eloquent ORM over a MySQL database with InnoDB tables. I don't have any problem using raw SQL commands directly, but I don't want to switch to a different table type.

You can use handlers if you want to track any specific error. But I dont think that commiting only a part of the transaction is a very good idea.

You can also check the signal

You could send your logs to a MyISAM table (since MyISAM tables do not support transactions , COMMIT or ROLLBACK and the likes have no effect on them).

[edit]
... but I just noticed the part where you wrote: "I don't want to switch to a different table type". As 3m1n4 suggests , it is not possible to commit an arbitrary part of a transaction * . The only workaround I can think of is populating log tables from a different transaction.

* It is possible to partially rollback a transaction through the use of save points , but I don't think this is relevant to your problem

One of the first prinicpals of Relational DB is ACID (Atomicity, Consistency, Isolation, Durability). I think that atomicity explains a lot of what you are asking. Atomicity ensures that transactions are always all or nothing. That means if one part of transaction fails whole transaction will be rolled back, and DB stays in unchanged state.

INSERT, UPDATE and DELETE are statemants that are Autocomitted, but this behavior can be overridden if you make them a part of a transaction. In mySql that is START TRANSACTION statement and whole Transaction is commited at the end. See this links for further explanation:

http://dev.mysql.com/doc/refman/5.6/en/commit.html

Also a very good Q and A: https://dba.stackexchange.com/questions/4252/do-inserts-get-auto-committed

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM