Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New behavior for implicit transactions [DNET483] #470

Closed
firebird-automations opened this issue Jan 20, 2013 · 5 comments
Closed

New behavior for implicit transactions [DNET483] #470

firebird-automations opened this issue Jan 20, 2013 · 5 comments

Comments

@firebird-automations
Copy link

Submitted by: F.D.Castel (fdcastel)

Attachments:
DNET-483-FDCastel-Proposal.patch

In the current implementation implicit transactions are being commited after each command execution (and restarted again on the next one). This is not the ideal since it causes a lot of overhead in Firebird.

Of course, with Firebird, the best practice IS to use explicit transactions. So, at first look, this is not a big problem.

However, in db-agnostic scenarios like ORMs the code is often NOT aware of this and expect to use DbCommands without transactions. So, in this case, they are taking a lot of time and server resources.

E.g.: It took me about 20 minutes to reverse engineer some moderately sized (400 tables) Firebird database into Entity Framework. At first I though it was EF fault, but after seeing the performance problems described in DNET280 i did realize that was actually the provider fault.

Given all that, I propose to change the current behavior from "one commit after each execute" to "one commit after FbCommand disposal" when using implicit transactions. This could bring some breaks in compatibility, but it will bring the performance near to levels similar to the other providers.

@firebird-automations
Copy link
Author

Commented by: F.D.Castel (fdcastel)

Attached is a patch to implement this suggestion using a new property: ImplicitTransactionBehavior (in FbCommand)

The default behavior is CommitOnExecute, to keep backward compatibility. This is not the ideal, since it won't fix the problem with ORMs (or any code using System.Data.Common). The default should be CommitOnDispose, but this could be changed in a next "bigger" release (3.1 or 4.0)

In this patch there is also some performance tests (not actual tests, should not be commited into /trunk) only to show the difference between the two behaviors:

ImplicitTransaction_CommitOnExecute: 100000 commands in 17,949 seconds; 5571,34102178394 commands per second
ImplicitTransaction_CommitOnDispose: 100000 commands in 7,578 seconds; 13196,093956189 commands per second

Even with CommitOnDispose as the default behavior, all current unit tests run successfully.

Two considerations:

1) In ICloneable.Clone() there is a duplicate assignment of UpdatedRowSource. Is it necessary?

2) In Release() I've kept the rollback for backward compatibility only. I believe it could be always a commit, in both cases.

@firebird-automations
Copy link
Author

Modified by: F.D.Castel (fdcastel)

Attachment: DNET483-FDCastel-Proposal.patch [ 12279 ]

@firebird-automations
Copy link
Author

Commented by: @cincuranet

This is not going to happen. This behavior is standard in whole http://ADO.NET world (and not only there), and any provider is expected to behave like this.

The ORMs handle transactions, very often, per unit-of-work (when pushing it to database), and you can (should) use TransactionScope (or custom tx handling depending on ORM) if you need more control.

Getting EF model is done using one command (but fairly huge), so there's actually sequence of starting implicit transaction, executing command and committing. But because the command is huge (takes a time to execute, especially because FB's optimizer isn't that good in this case) and it's loading huge amount of data (FB's wire protocol isn't that succinct as it could be (and there's still room for improvement on client side as well)).

@firebird-automations
Copy link
Author

Modified by: @cincuranet

status: Open [ 1 ] => Closed [ 6 ]

resolution: Won't Fix [ 2 ]

@firebird-automations
Copy link
Author

Commented by: F.D.Castel (fdcastel)

You're right. I did the same test with SqlServer and using implicit transaction is (marginally) slower.

* Using implicit transaction:
SqlServer: 100000 commands in 6,2946 seconds; 15886,6329870047 commands per second

* Using explicit transaction:
SqlServer: 100000 commands in 6,1479 seconds; 16265,7167488085 commands per second

So, my suggestion was a bad call. The current implementation follow the http://ADO.NET guidelines for providers and must be kept. Thank you very much for the pointers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants