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
upsert()
should do ON CONFLICT DO UPDATE/NOTHING in postgresql
#9972
Comments
I'm not sure on the performance for |
I've been noticing many weird upsert conflict errors in prod when I have batched queries (e.g., from Apollo) hitting the same endpoint with the same uniqueness criterion: I thought I was doing something wrong until I realized that I think there should be a big red bold warning in the docs at the very least that upsert is not a true upsert, since I'm sure this can potentially cause a severe race conditions for others. The workaround here would be to wrap this in an interactive transaction, but unfortunately there's a bug currently with interactive transactions that causes a deadlock... #9846. |
I'm hitting the same issue in a websocket handler. When two messages including the same key are received nothing about concurrency can be done from my side. |
In my experience Postgres' upsert functionality isn't safe from race conditions either -- at least between concurrent transactions. We ended up replacing instances of (Disclaimer: this is likely a sub-optimal implementation; I've also typed it from memory so it's possible there are bugs. 😄 ) CREATE OR REPLACE FUNCTION select_or_insert_foo(p_foo_name text)
RETURNS int
LANGUAGE plpgsql
AS
$$
DECLARE
v_foo_id foo.id%type;
BEGIN
SELECT id
INTO v_foo_id
FROM foo
WHERE name = p_foo_name;
IF v_foo_id IS NULL THEN
PERFORM pg_advisory_xact_lock(hashtext('select_or_insert_foo'), hashtext(p_foo_name));
SELECT id
INTO v_foo_id
FROM foo
WHERE name = p_foo_name;
IF v_foo_id IS NULL THEN
INSERT INTO foo (name)
VALUES (p_foo_name)
RETURNING id INTO v_foo_id;
END IF;
END IF;
RETURN v_foo_id;
END;
$$; |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
Ok, so this is kind of one solution for the big issue we have with upserts, updates, deletes and all that. I'll put this in our initiative for the next team to take a look at. We are all of us really hard trying to solve this and many other similar issues for the next release. For the person implementing a fix, be aware that https://stackoverflow.com/questions/26081236/update-where-race-conditions-postgres-read-committed We have some other ways of doing this too, one of them would be to select for update, which locks the rows and should prevent the issue from happening. |
We are treating this issue as the feature/improvement suggestion it is. The actual problems with |
upsert()
should do ON CONFLICT DO UPDATE/NOTHING in postgresql
With our latest release we support |
Originally posted by @windowsdeveloperwannabe in #8134 (comment)
SELECT then INSERT causes race conditions. Postgres has native support for upsert. It's surprising that prisma has a function explicitly named
upsert()
that doesn't use this feature.The text was updated successfully, but these errors were encountered: