Quantcast
Viewing all articles
Browse latest Browse all 207

Do I need an explicit FOR UPDATE lock in a CTE in UPDATE?

In Postgres 13, I have a table which gets updated frequently. However, the update query is rather complicated and uses the same values multiple times. So, using a CTE seems quite a logical thing to do.

A simplified example looks like this:

WITH my_cte AS (    SELECT          my_id,          CASE WHEN my_value1 > 100 THEN 50 ELSE 10 END AS my_addition         FROM my_table          WHERE my_id = $1)UPDATE my_table        SET my_value1 = my_table.my_value1 + my_cte.my_addition,            my_value2 = my_table.my_value2 + my_cte.my_additionFROM my_cteWHERE my_table.my_id = my_cte.my_id

Now I'm wondering: What would happen if between the SELECT in the CTE and the UPDATE, the table is updated by another query, changing my_value1 on thus, the calculation of my_addition were to become outdated and wrong when the UPDATE happens. Can such a situation occur? Or does Postgres set an implicit lock automatically?

If Postgres does no magic here and I need to take care of it myself: Would it be sufficient to do FOR UPDATE in the SELECT of the CTE?

Sorry if I did not make myself clear here: It's not that I want to "see" those concurrent modifications, I want to prevent them i.e. once the calculation the SELECT is done, no other queries might modify that very row till the UPDATE is done.

In real life, what I mocked here by CASE WHEN my_value1 > 100 THEN 50 ELSE 10 END is about 20 lines long and I need it at about 5 places in the UPDATE. Since I'm a big fan of "Do not repeat yourself", I think a CTE is the way to go. Or is there a better way to avoid copy & pasting in an UPDATE without a CTE?


Viewing all articles
Browse latest Browse all 207

Trending Articles