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

Add transaction support #1

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

tnt-dev
Copy link

@tnt-dev tnt-dev commented Dec 3, 2015

No description provided.

@ostinelli
Copy link
Owner

Thank you Pavel for this req. Can you please also add how to use this in the README file, and squash the commit? I'll pull this in once done. Thanks!

@tnt-dev
Copy link
Author

tnt-dev commented Jan 2, 2016

README updated, sorry for delay.

@ostinelli
Copy link
Owner

Thank you for your input. However, if this is the intended usage then I'm afraid it won't work.

The issue is that when you call a transaction, inside of its fun you're calling pgpool:squery/2 again:

pgpool:transaction(db1_name,
  fun(C) ->
    pgpool:squery(C, "DELETE FROM users WHERE foo = true"),
    pgpool:squery(C, "UPDATE users SET bar = 100"),
    pgpool:squery(C, "SELECT * FROM users")
  end
).

Fact is, pgpool:squery/2 checks out a worker:

squery(DatabaseName, Sql) ->
    poolboy:transaction(DatabaseName, fun(Worker) ->
        gen_server:call(Worker, {squery, Sql}, infinity)
    end).

Therefore, every time you run a query inside of the transaction fun, it might actually use a different worker, hence a different connection. To my understanding, you can't have a transaction run on different connections.

We could, though, do something like:

pgpool:transaction(db1_name,
  fun() ->
    pgpool:squery("DELETE FROM users WHERE foo = true"),
    pgpool:squery("UPDATE users SET bar = 100"),
    pgpool:squery("SELECT * FROM users")
  end
).

And then ensure that pgpool:squery/1 always uses the same connection.

@aberman
Copy link

aberman commented May 8, 2016

I think there should be a distinct difference between sharing a connection between multiple statements and a true transaction (BEGIN...COMMIT). Poolboy calls their checkout/checkin a transaction, but it's a bit of a misnomer when you think about a database transaction. Since this library uses poolboy for a distinct reason to access Postgres, I think there should be a proper difference, something like with_connection to represent running statements with a shared connection and with_transaction, which not only shares a connection, but actually runs inside a database transaction. The epgpsql driver provides the with_transaction/2 function to do the db transaction.

@ostinelli
Copy link
Owner

Yes @aberman, that is exactly my point for not merging this PR in.

BTW, now PGPool has the batch/2 function which can easily be extended to run inside of a database transaction.

Would you like to see this feature in PGPool?

@aberman
Copy link

aberman commented May 8, 2016

@ostinelli, I think the use of a db transaction should be left up to the user of the library. My use of batch statements is usually when I'm doing some offline process and I might have thousands of inserts/updates. 95% of the time I just want to skip the bad insert/update and log it, not have the entire transaction fail.

I think pgpool should provide the tools just like the driver, but shouldn't make all the decisions for the user. To me, the purpose of the library is to tack on some useful features to the driver, which means it's the interface I use to access the db, instead of the driver. That, to me, means it should replicate everything or most of what the driver does as well. That might be outside the scope of what you wanted to do, but I do foresee that the more people that use this, the more requests you're going to get to add that sort of flexibility.

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

Successfully merging this pull request may close these issues.

3 participants