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

This should set the transaction status to in transaction #161

Open
davecramer opened this issue Sep 22, 2022 · 17 comments
Open

This should set the transaction status to in transaction #161

davecramer opened this issue Sep 22, 2022 · 17 comments
Assignees
Labels
enhancement New feature or request

Comments

@karenc-bq
Copy link
Contributor

@davecramer I pushed a fix in #163

@karenc-bq
Copy link
Contributor

I took the change out of #163. We will add the change in a different PR to make sure we considered all the relevant cases

@hsuamz hsuamz added the enhancement New feature or request label Oct 3, 2022
@github-actions github-actions bot added the Stale label Nov 7, 2022
@davecramer
Copy link
Contributor Author

This should remain open until fixed

@davecramer davecramer reopened this Nov 28, 2022
@github-actions github-actions bot removed the Stale label Dec 5, 2022
@aaron-congo
Copy link
Contributor

aaron-congo commented Dec 5, 2022

Hi @davecramer, there are a couple workflows where setting transaction status based on setAutoCommit is problematic.

  1. Switching autocommit values within a transaction. For example, you can start a transaction while autocommit is false, then, while in the same transaction, you can call setAutoCommit(true). In this case, even though autocommit is true, you are still in a transaction
  2. While autocommit is on, you can execute "START TRANSACTION". Again, even though autocommit is on, the transaction status should show we are in a transaction until commit is called.

The current implementation for tracking transaction status handles these two scenarios. Admittedly, they seem like strange workflows so whether they follow recommended practices or not is another question. Regardless, since the existing drivers seem to allow this behavior, I believe we should as well.

If that makes sense, let me know and I can close this ticket. Otherwise, let me know if you have any questions. Thanks!

@davecramer
Copy link
Contributor Author

The spec says this: which suggests otherwise.

NOTE: If this method is called during a transaction and the auto-commit mode is changed, the transaction is committed. If setAutoCommit is called and the auto-commit mode is not changed, the call is a no-op.

@aaron-congo
Copy link
Contributor

Ah okay, thanks for pointing that out, I wasn't aware of that. I'll do some more investigation and get back to you

@davecramer
Copy link
Contributor Author

So it appears that mysql does indeed do some funky stuff but PostgreSQL doesn't https://dev.mysql.com/doc/refman/8.0/en/implicit-commit.html
Mysql will actually commit the transaction in flight with another begin (most of the time)

The [BEGIN](https://dev.mysql.com/doc/refman/8.0/en/commit.html) statement differs from the use of the BEGIN keyword that starts a [BEGIN ... END](https://dev.mysql.com/doc/refman/8.0/en/begin-end.html) compound statement. The latter does not cause an implicit commit. See [Section 13.6.1, “BEGIN ... END Compound Statement”](https://dev.mysql.com/doc/refman/8.0/en/begin-end.html).

PostgreSQL will give you a warning saying there is already a transaction in process, but does not commit the transaction in flight.

@aaron-congo
Copy link
Contributor

aaron-congo commented Dec 6, 2022

Hi Dave, could you give me more context regarding your last comment? We were discussing whether setAutoCommit should set inTransaction, but your comment seems to be referring to implicit commits. Just want to make sure I'm understanding.

Also, I did a couple tests with the mysql and postgres community drivers switching autocommit while inside a transaction. Both drivers commit the transaction when switching autocommit from false to true inside the transaction, but neither committed the transaction when switching autocommit from true to false. Should they be committing in this scenario, given the spec you mentioned?

@davecramer
Copy link
Contributor Author

My last comment is suggesting that it appears there are real differences to the way begin is handled inside a transaction.

As for committing when going from true to false. I don't think there is a transaction that needs to be committed at that point as the are in autocommit mode and every statement is committed.

@aaron-congo
Copy link
Contributor

Gotcha, yeah that's something to keep in mind, thanks!

For committing when going from true to false, what about the case where the user has autocommit on and executes "START TRANSACTION"? I've tested with the mysql and postgres driver and it appears both will let you start a transaction with autocommit on and switch autocommit to false inside the transaction, but neither will commit the transaction in this case

@davecramer
Copy link
Contributor Author

Well the spec also says you shouldn't do that :)

Note: When configuring a Connection, JDBC applications should use the appropriate Connection method such as setAutoCommit or setTransactionIsolation. Applications should not invoke SQL commands directly to change the connection's configuration when there is a JDBC method available. By default a Connection object is in auto-commit mode, which means that it automatically commits changes after executing each statement. If auto-commit mode has been disabled, the method commit must be called explicitly in order to commit changes; otherwise, database changes will not be saved.

Since the drivers are generally not inspecting SQL they have no way of knowing that you have started a transaction so they also have no way to know whether to commit the transaction. The drivers can only control what happens through the API

@aaron-congo
Copy link
Contributor

Okay thanks, just wanted to verify that executing "START TRANSACTION" is not considered valid according to the spec then? That quote you provided seems to clearly say that, for example, users should not execute "COMMIT" since there is a directly corresponding JDBC method: Connection#commit(). However its less clear to me whether that quote is implying "START TRANSACTION" is not considered valid, since there is not a directly corresponding startTransaction() method. I know setting autocommit false is the usual way of doing things though. Just trying to get clarity, thanks!

@davecramer
Copy link
Contributor Author

Doing it that way makes it difficult for the driver to know what the state is. It appears that MySQL tracks it. PostgreSQL does not

@aaron-congo
Copy link
Contributor

Right, is "START TRANSACTION" invalid according the JDBC API though? I still can't tell, I can't find anywhere in the spec that clarifies this specific scenario

@davecramer
Copy link
Contributor Author

it's not "invalid" there's just no specific support for using it.

@aaron-congo
Copy link
Contributor

aaron-congo commented Dec 13, 2022

Right, thanks for the clarification. With this in mind it sounds like the driver does not necessarily have to support tracking transactions for the scenario where the user starts a transaction with "START TRANSACTION" or "BEGIN". Perhaps it might be useful to some customers but it sounds like starting transactions in this way is uncommon (if used at all) and not recommended so we might consider simplifying transaction tracking to exclude tracking this scenario. Does this sound accurate or did I misunderstand?

@davecramer
Copy link
Contributor Author

I think this is accurately summarizes the situation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants