Implement “account” transactions in postgresql
I am looking into on different ways a simple account functionality that can be implemented in Postgresql 9.5. I would like to be able to do it with maximum of "Repeatable read" as transaction isolation level. The reason why it should be "Repeatable read" isolation level is that we have detected a high level of collisions "serializable" isolation level and even with a retry strategy around 10 times within 10 seconds it still fails because of the amount of collisions.
- Deposit money
- Withdraw money
- Cannot withdraw money if balance of the user is less than zero (sum of amount for user)
- Balance must never be able to go below zero (sum of amount for user)
It should handle multiple connections and multiple users and the same user can initiate deposits and withdraws in different connections.
The only solution I currently have is to do something like the following:
For deposits:
- Allow deposit money directly as an insert.
For withdraws:
- Check balance > amount of withdraw before continue.
- Insert withdraw money transaction with status initiated.
- Update withdraw money transaction status failed if sum of transactions for user in status (initiated, completed) is less than zero.
- Update withdraw money transaction status completed if status is initiated.
Any materials or examples are welcomed.
postgresql
bumped to the homepage by Community♦ 10 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
add a comment |
I am looking into on different ways a simple account functionality that can be implemented in Postgresql 9.5. I would like to be able to do it with maximum of "Repeatable read" as transaction isolation level. The reason why it should be "Repeatable read" isolation level is that we have detected a high level of collisions "serializable" isolation level and even with a retry strategy around 10 times within 10 seconds it still fails because of the amount of collisions.
- Deposit money
- Withdraw money
- Cannot withdraw money if balance of the user is less than zero (sum of amount for user)
- Balance must never be able to go below zero (sum of amount for user)
It should handle multiple connections and multiple users and the same user can initiate deposits and withdraws in different connections.
The only solution I currently have is to do something like the following:
For deposits:
- Allow deposit money directly as an insert.
For withdraws:
- Check balance > amount of withdraw before continue.
- Insert withdraw money transaction with status initiated.
- Update withdraw money transaction status failed if sum of transactions for user in status (initiated, completed) is less than zero.
- Update withdraw money transaction status completed if status is initiated.
Any materials or examples are welcomed.
postgresql
bumped to the homepage by Community♦ 10 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
Can you ever have negative balances?
– Evan Carroll
Jan 3 '17 at 16:39
I'm also not sure what you mean with status initialized/failed
– Evan Carroll
Jan 3 '17 at 20:27
what solution did you find for this?
– frostymarvelous
Jun 11 '18 at 18:23
add a comment |
I am looking into on different ways a simple account functionality that can be implemented in Postgresql 9.5. I would like to be able to do it with maximum of "Repeatable read" as transaction isolation level. The reason why it should be "Repeatable read" isolation level is that we have detected a high level of collisions "serializable" isolation level and even with a retry strategy around 10 times within 10 seconds it still fails because of the amount of collisions.
- Deposit money
- Withdraw money
- Cannot withdraw money if balance of the user is less than zero (sum of amount for user)
- Balance must never be able to go below zero (sum of amount for user)
It should handle multiple connections and multiple users and the same user can initiate deposits and withdraws in different connections.
The only solution I currently have is to do something like the following:
For deposits:
- Allow deposit money directly as an insert.
For withdraws:
- Check balance > amount of withdraw before continue.
- Insert withdraw money transaction with status initiated.
- Update withdraw money transaction status failed if sum of transactions for user in status (initiated, completed) is less than zero.
- Update withdraw money transaction status completed if status is initiated.
Any materials or examples are welcomed.
postgresql
I am looking into on different ways a simple account functionality that can be implemented in Postgresql 9.5. I would like to be able to do it with maximum of "Repeatable read" as transaction isolation level. The reason why it should be "Repeatable read" isolation level is that we have detected a high level of collisions "serializable" isolation level and even with a retry strategy around 10 times within 10 seconds it still fails because of the amount of collisions.
- Deposit money
- Withdraw money
- Cannot withdraw money if balance of the user is less than zero (sum of amount for user)
- Balance must never be able to go below zero (sum of amount for user)
It should handle multiple connections and multiple users and the same user can initiate deposits and withdraws in different connections.
The only solution I currently have is to do something like the following:
For deposits:
- Allow deposit money directly as an insert.
For withdraws:
- Check balance > amount of withdraw before continue.
- Insert withdraw money transaction with status initiated.
- Update withdraw money transaction status failed if sum of transactions for user in status (initiated, completed) is less than zero.
- Update withdraw money transaction status completed if status is initiated.
Any materials or examples are welcomed.
postgresql
postgresql
asked Nov 30 '16 at 15:55
Dennis SoegaardDennis Soegaard
213
213
bumped to the homepage by Community♦ 10 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
bumped to the homepage by Community♦ 10 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
Can you ever have negative balances?
– Evan Carroll
Jan 3 '17 at 16:39
I'm also not sure what you mean with status initialized/failed
– Evan Carroll
Jan 3 '17 at 20:27
what solution did you find for this?
– frostymarvelous
Jun 11 '18 at 18:23
add a comment |
Can you ever have negative balances?
– Evan Carroll
Jan 3 '17 at 16:39
I'm also not sure what you mean with status initialized/failed
– Evan Carroll
Jan 3 '17 at 20:27
what solution did you find for this?
– frostymarvelous
Jun 11 '18 at 18:23
Can you ever have negative balances?
– Evan Carroll
Jan 3 '17 at 16:39
Can you ever have negative balances?
– Evan Carroll
Jan 3 '17 at 16:39
I'm also not sure what you mean with status initialized/failed
– Evan Carroll
Jan 3 '17 at 20:27
I'm also not sure what you mean with status initialized/failed
– Evan Carroll
Jan 3 '17 at 20:27
what solution did you find for this?
– frostymarvelous
Jun 11 '18 at 18:23
what solution did you find for this?
– frostymarvelous
Jun 11 '18 at 18:23
add a comment |
1 Answer
1
active
oldest
votes
Good Idea For deposits: Allow deposit money directly as an insert.
Bad Idea For withdraws: Check balance > amount of withdraw before continue.
- Consider instead having a CHECK (balance >= 0), then just allow the transaction to fail.
I'm not sure about the rest of them.. You mention all this STATUS stuff, but what does it matter?
BEGIN;
UPDATE accounts
SET balance = balance - 100
WHERE name = 'Bob';
UPDATE accounts
SET balance = balance + 100
WHERE name = 'Sally';
END;
- If the balance on accounts would go under 0 with the deduction, it'll simply fail there.
- If it passes then you will see bob's balance go down for your transaction.
- Adding 100 to Sally's account is a no-brainier, but you have a lock on that too now.
The default transaction levels permit phantom reads, but here that's not an issue. The first statement is an UPDATE
. It either works, or it doesn't. If it works, UPDATE
gets ROW EXCLUSIVE
lock. No other UPDATE
s will work on that table until the transaction is committed.
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "182"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f156791%2fimplement-account-transactions-in-postgresql%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Good Idea For deposits: Allow deposit money directly as an insert.
Bad Idea For withdraws: Check balance > amount of withdraw before continue.
- Consider instead having a CHECK (balance >= 0), then just allow the transaction to fail.
I'm not sure about the rest of them.. You mention all this STATUS stuff, but what does it matter?
BEGIN;
UPDATE accounts
SET balance = balance - 100
WHERE name = 'Bob';
UPDATE accounts
SET balance = balance + 100
WHERE name = 'Sally';
END;
- If the balance on accounts would go under 0 with the deduction, it'll simply fail there.
- If it passes then you will see bob's balance go down for your transaction.
- Adding 100 to Sally's account is a no-brainier, but you have a lock on that too now.
The default transaction levels permit phantom reads, but here that's not an issue. The first statement is an UPDATE
. It either works, or it doesn't. If it works, UPDATE
gets ROW EXCLUSIVE
lock. No other UPDATE
s will work on that table until the transaction is committed.
add a comment |
Good Idea For deposits: Allow deposit money directly as an insert.
Bad Idea For withdraws: Check balance > amount of withdraw before continue.
- Consider instead having a CHECK (balance >= 0), then just allow the transaction to fail.
I'm not sure about the rest of them.. You mention all this STATUS stuff, but what does it matter?
BEGIN;
UPDATE accounts
SET balance = balance - 100
WHERE name = 'Bob';
UPDATE accounts
SET balance = balance + 100
WHERE name = 'Sally';
END;
- If the balance on accounts would go under 0 with the deduction, it'll simply fail there.
- If it passes then you will see bob's balance go down for your transaction.
- Adding 100 to Sally's account is a no-brainier, but you have a lock on that too now.
The default transaction levels permit phantom reads, but here that's not an issue. The first statement is an UPDATE
. It either works, or it doesn't. If it works, UPDATE
gets ROW EXCLUSIVE
lock. No other UPDATE
s will work on that table until the transaction is committed.
add a comment |
Good Idea For deposits: Allow deposit money directly as an insert.
Bad Idea For withdraws: Check balance > amount of withdraw before continue.
- Consider instead having a CHECK (balance >= 0), then just allow the transaction to fail.
I'm not sure about the rest of them.. You mention all this STATUS stuff, but what does it matter?
BEGIN;
UPDATE accounts
SET balance = balance - 100
WHERE name = 'Bob';
UPDATE accounts
SET balance = balance + 100
WHERE name = 'Sally';
END;
- If the balance on accounts would go under 0 with the deduction, it'll simply fail there.
- If it passes then you will see bob's balance go down for your transaction.
- Adding 100 to Sally's account is a no-brainier, but you have a lock on that too now.
The default transaction levels permit phantom reads, but here that's not an issue. The first statement is an UPDATE
. It either works, or it doesn't. If it works, UPDATE
gets ROW EXCLUSIVE
lock. No other UPDATE
s will work on that table until the transaction is committed.
Good Idea For deposits: Allow deposit money directly as an insert.
Bad Idea For withdraws: Check balance > amount of withdraw before continue.
- Consider instead having a CHECK (balance >= 0), then just allow the transaction to fail.
I'm not sure about the rest of them.. You mention all this STATUS stuff, but what does it matter?
BEGIN;
UPDATE accounts
SET balance = balance - 100
WHERE name = 'Bob';
UPDATE accounts
SET balance = balance + 100
WHERE name = 'Sally';
END;
- If the balance on accounts would go under 0 with the deduction, it'll simply fail there.
- If it passes then you will see bob's balance go down for your transaction.
- Adding 100 to Sally's account is a no-brainier, but you have a lock on that too now.
The default transaction levels permit phantom reads, but here that's not an issue. The first statement is an UPDATE
. It either works, or it doesn't. If it works, UPDATE
gets ROW EXCLUSIVE
lock. No other UPDATE
s will work on that table until the transaction is committed.
answered Jan 3 '17 at 21:03
Evan CarrollEvan Carroll
31.8k967216
31.8k967216
add a comment |
add a comment |
Thanks for contributing an answer to Database Administrators Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f156791%2fimplement-account-transactions-in-postgresql%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Can you ever have negative balances?
– Evan Carroll
Jan 3 '17 at 16:39
I'm also not sure what you mean with status initialized/failed
– Evan Carroll
Jan 3 '17 at 20:27
what solution did you find for this?
– frostymarvelous
Jun 11 '18 at 18:23