1

I have a function which calls itself to resolve a hierarchy. Without any volatility declaration, it gives me the desired result (that means the recursion ends). As a performance optimization, I declared the function as STABLE and executed it again. Now it always aborts with the above error, telling me to increase the max_stack_depth which sounds like endless recursion to me.

What is happening here?

6
  • Welcome to DBA.SE. Did you try and increase the max_stack_depth parameter? What happened? What is your current value? Have a look at function volatility in the official PostgreSQL documentation.
    – John K. N.
    Commented Jan 20, 2020 at 12:55
  • 1
    Post a minimal example, including create table and insert -statements together with the function itself Commented Jan 20, 2020 at 12:56
  • @Johnakahot2use It's the default (2 MB). I can increase it to 3 MB with the same error. With 4 MB, the server won't start. I've read all of the documentation but I'm still lost.
    – xehpuk
    Commented Jan 20, 2020 at 13:09
  • @Lennart I hope I'll find the time…
    – xehpuk
    Commented Jan 20, 2020 at 13:10
  • 2
    Without the function's code this is impossible to answer. But why a function and not a recursive common table expression
    – user1822
    Commented Jan 20, 2020 at 13:11

1 Answer 1

2

A function may not see the same state of the database depending on whether it's VOLATILE or not, when this state is changing during the execution of the SQL statement it's called from, either because of the statement itself or because of another transaction if the isolation level is Read Committed.

This is documented in https://www.postgresql.org/docs/current/xfunc-volatility.html

For functions written in SQL or in any of the standard procedural languages, there is a second important property determined by the volatility category, namely the visibility of any data changes that have been made by the SQL command that is calling the function. A VOLATILE function will see such changes, a STABLE or IMMUTABLE function will not. This behavior is implemented using the snapshotting behavior of MVCC (see Chapter 13): STABLE and IMMUTABLE functions use a snapshot established as of the start of the calling query, whereas VOLATILE functions obtain a fresh snapshot at the start of each query they execute.

If your function reads the database and follows different paths depending on what it reads, it's quite possible that it goes into infinite recursion only when it's not VOLATILE. Looking at the code might be revealing.

7
  • The function (and the outer statement) does not write to the database.
    – xehpuk
    Commented Jan 20, 2020 at 13:08
  • @xehpuk: nevertheless, a volatile function does not necessarily see the same state as if would if non-volatile. In the read committed isolation level, the state of the data it sees may come from a different transaction that just committed. Commented Jan 20, 2020 at 13:39
  • Nothing else is currently running on the database.
    – xehpuk
    Commented Jan 20, 2020 at 13:44
  • @xehpuk: okay, please show a reproducible example. Commented Jan 20, 2020 at 13:58
  • This answer is only relevant if the function is invoked by a data modifying statement, right? Commented Jan 20, 2020 at 15:52

Not the answer you're looking for? Browse other questions tagged or ask your own question.