Обсуждение: ResultSet storing all rows with defaulftFetchSize to 5000
... ResultSet holdability is HOLD_CURSOR_OVER_COMMIT. ...And the postgresql comunity jdbc driver 9.4 documentation said:"... There are a number of restrictions which will make the driver silently fall back to fetch the whole ResultSet ..."
On Wed, Feb 7, 2018 at 1:00 PM, Jaime Soler <jaime.soler@gmail.com> wrote:... ResultSet holdability is HOLD_CURSOR_OVER_COMMIT. ...And the postgresql comunity jdbc driver 9.4 documentation said:"... There are a number of restrictions which will make the driver silently fall back to fetch the whole ResultSet ..."And the statement must be created with a ResultSet holdability of CLOSE_CURSORS_AT_COMMIT - which is not documented. https://github.com/pgjdbc/pgjdbc/pull/1105 submitted to fix that. The relevant code fragment from org.postgresql.jdbc.PgStatement.java is ... // Enable cursor-based resultset if possible.if (fetchSize > 0 && !wantsScrollableResultSet() && !connection.getAutoCommit()&& !wantsHoldableResultSet()) {flags |= QueryExecutor.QUERY_FORWARD_CURSOR; }And the fragment from org.postgresql.v3.QueryExecutorImpl.java ... boolean usePortal = (flags & QueryExecutor.QUERY_FORWARD_CURSOR) != 0 && !noResults && !noMeta && fetchSize > 0 && !describeOnly;
Jaime,9.4.1208 is considerably out of date. You may want to upgrade.On 8 February 2018 at 19:13, Brad DeJong <bpd0018@gmail.com> wrote:On Wed, Feb 7, 2018 at 1:00 PM, Jaime Soler <jaime.soler@gmail.com> wrote:... ResultSet holdability is HOLD_CURSOR_OVER_COMMIT. ...And the postgresql comunity jdbc driver 9.4 documentation said:"... There are a number of restrictions which will make the driver silently fall back to fetch the whole ResultSet ..."And the statement must be created with a ResultSet holdability of CLOSE_CURSORS_AT_COMMIT - which is not documented. https://github.com/pgjdbc/pgjdbc/pull/1105 submitted to fix that. The relevant code fragment from org.postgresql.jdbc.PgStatement.java is ... // Enable cursor-based resultset if possible.if (fetchSize > 0 && !wantsScrollableResultSet() && !connection.getAutoCommit()&& !wantsHoldableResultSet()) {flags |= QueryExecutor.QUERY_FORWARD_CURSOR; }And the fragment from org.postgresql.v3.QueryExecutorImpl.java ... boolean usePortal = (flags & QueryExecutor.QUERY_FORWARD_CURSOR) != 0 && !noResults && !noMeta && fetchSize > 0 && !describeOnly;
Well testing with last version v42.2.1 I see same behaviour, org.postgresql.jdbc.PgStatement. java and org.postgresql.core.v3. QueryExecutorImpl.java has same condition to use Portal as version 9.4.1208: private void executeInternal(CachedQuery cachedQuery, ParameterList queryParameters, int flags)throws SQLException {closeForNextExecution();// Enable cursor-based resultset if possible.if (fetchSize > 0 && !wantsScrollableResultSet() && !connection.getAutoCommit()&& !wantsHoldableResultSet()) {flags |= QueryExecutor.QUERY_FORWARD_CURSOR; }private void sendOneQuery(SimpleQuery query, SimpleParameterList params, int maxRows,int fetchSize, int flags) throws IOException {...boolean usePortal = (flags & QueryExecutor.QUERY_FORWARD_CURSOR) != 0 && !noResults && !noMeta && fetchSize > 0 && !describeOnly;I am helping to migrate a Oracle application to run on Postgresql, and the default holdability setting at oracle is HOLD_CURSOR_OVER_COMMIT so I have tried to set this HOLD_CURSOR_OVER_COMMIT as default holdability setting. Could you explain me why I couldn't use fetchSize in a transaction( autocommit = false ) and keeping those ResultSet available after a commit ? is there a limitation of the jdbc driver or it comes from server side ?What the application does is something similar to:postgres=# begin;BEGINedb=# declare p cursor with hold for select * from foo;DECLARE CURSORpostgres=# fetch next p;id----1postgres=# fetch next p;id----2postgres=# fetch next p;id----3postgres=# fetch next p;id----4postgres=# commit;COMMIT-- after validating a chunk of data, continue with the next chunkpostgres=# begin;BEGINpostgres=# fetch next p;id----5postgres=# fetch next p;id----6postgres=# commit;Regards2018-02-09 23:09 GMT+01:00 Dave Cramer <pg@fastcrypt.com>:Jaime,9.4.1208 is considerably out of date. You may want to upgrade.On 8 February 2018 at 19:13, Brad DeJong <bpd0018@gmail.com> wrote:On Wed, Feb 7, 2018 at 1:00 PM, Jaime Soler <jaime.soler@gmail.com> wrote:... ResultSet holdability is HOLD_CURSOR_OVER_COMMIT. ...And the postgresql comunity jdbc driver 9.4 documentation said:"... There are a number of restrictions which will make the driver silently fall back to fetch the whole ResultSet ..."And the statement must be created with a ResultSet holdability of CLOSE_CURSORS_AT_COMMIT - which is not documented. https://github.com/pgjdbc/pgjdbc/pull/1105 submitted to fix that.
The relevant code fragment from org.postgresql.jdbc.PgStatement.java is ... // Enable cursor-based resultset if possible.if (fetchSize > 0 && !wantsScrollableResultSet() && !connection.getAutoCommit()&& !wantsHoldableResultSet()) {flags |= QueryExecutor.QUERY_FORWARD_CURSOR; }And the fragment from org.postgresql.v3.QueryExecutorImpl.java ... boolean usePortal = (flags & QueryExecutor.QUERY_FORWARD_CURSOR) != 0 && !noResults && !noMeta && fetchSize > 0 && !describeOnly;
Vladimir Sitnikov <sitnikov.vladimir@gmail.com> writes: > I have no idea why PostgreSQL closes all the cursors as transaction > ends, Because the SQL standard says so. If a cursor isn't declared WITH HOLD, then it's implicitly closed at transaction commit, cf SQL:2011 4.33 "Cursors": An open cursor that was not defined as a holdable cursor is also closed by a <commit statement>. Also, 14.2 <cursor properties> says that WITHOUT HOLD is the default assumption if you don't explicitly say WITH HOLD. (Yes, we do support WITH HOLD.) regards, tom lane
Jaime>I am helping to migrate a Oracle application to run on Postgresql, and the default holdability setting at oracle is HOLD_CURSOR_OVER_COMMIT so I have tried to set this HOLD_CURSOR_OVER_COMMIT as default holdability settingOk, that makes sense. I mean Oracle serves "fetch across commit" just fine (of course you can hit ORA-01555, but that is another story)>-- after validating a chunk of data, continue with the next chunk>postgres=# commit;>postgres=# fetch next p;Wait. Did you just make up the output?
Does PostgreSQL somehow supports "fetch across commit"?
What is your DB version?
I have no idea why PostgreSQL closes all the cursors as transaction ends, however that is the documented behavior.42.7.3. Using Cursors -> All portals are implicitly closed at transaction end. Therefore a refcursor value is usable to reference an open cursor only until the end of the transaction.
WITH HOLD
specifies that the cursor can continue to be used after the transaction that created it successfully commits. If WITH HOLD
is specified and the transaction that created the cursor successfully commits, the cursor can continue to be accessed by subsequent transactions in the same session. (But if the creating transaction is aborted, the cursor is removed.) A cursor created with WITH HOLD
is closed when an explicit CLOSE
command is issued on it, or the session ends. In the current implementation, the rows represented by a held cursor are copied into a temporary file or memory area so that they remain available for subsequent transactions.
pgjdbc just tries its best to avoid running into invalid (closed by backend) cursors, and pgjdbc fetches all the contents in HOLD_CURSOR_OVER_COMMIT case.It might be something to be discussed on pgsql-hackers mailing list.If only the DB did not close the portals...
Vladimir
Hi,2018-02-12 16:45 GMT+01:00 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>:Jaime>I am helping to migrate a Oracle application to run on Postgresql, and the default holdability setting at oracle is HOLD_CURSOR_OVER_COMMIT so I have tried to set this HOLD_CURSOR_OVER_COMMIT as default holdability settingOk, that makes sense. I mean Oracle serves "fetch across commit" just fine (of course you can hit ORA-01555, but that is another story)>-- after validating a chunk of data, continue with the next chunk>postgres=# commit;>postgres=# fetch next p;Wait. Did you just make up the output?No. it's a test case on the server database.Does PostgreSQL somehow supports "fetch across commit"?Yes, using WITH HOLD.What is your DB version?PostgreSQL 10.1 on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 6.3.0-12ubuntu2) 6.3.0 20170406, 64-bitI have no idea why PostgreSQL closes all the cursors as transaction ends, however that is the documented behavior.42.7.3. Using Cursors -> All portals are implicitly closed at transaction end. Therefore a refcursor value is usable to reference an open cursor only until the end of the transaction.Well I am not using PL/PGSQL cursor, but I think postgresql doesn't close portal after commit if you use WITH HOLD.
WITH HOLD
specifies that the cursor can continue to be used after the transaction that created it successfully commits.If
WITH HOLD
is specified and the transaction that created the cursor successfully commits, the cursor can continue to be accessed by subsequent transactions in the same session. (But if the creating transaction is aborted, the cursor is removed.) A cursor created withWITH HOLD
is closed when an explicitCLOSE
command is issued on it, or the session ends. In the current implementation, the rows represented by a held cursor are copied into a temporary file or memory area so that they remain available for subsequent transactions.pgjdbc just tries its best to avoid running into invalid (closed by backend) cursors, and pgjdbc fetches all the contents in HOLD_CURSOR_OVER_COMMIT case.It might be something to be discussed on pgsql-hackers mailing list.If only the DB did not close the portals...Don't you think that driver could use Portal and avoid storing all object when setFetchSize was set in a transaction ?
Vladimir Sitnikov <sitnikov.vladimir@gmail.com> writes: >> (Yes, we do support WITH HOLD.) > Oh, is it something available through extended query protocol? It's available through DECLARE CURSOR WITH HOLD. regards, tom lane
docs>In the current implementation, the rows represented by a held cursor are copied into a temporary file or memory area so that they remain available for subsequent transactions.
The backend materializes, so it is a sad thing.
Vladimir
Vladimir Sitnikov <sitnikov.vladimir@gmail.com> writes: > The backend materializes, so it is a sad thing. > Is there a change "with hold" can be implemented without materialization? That would not be an improvement. If we didn't materialize, then we'd have to retain the locks held by the transaction, as well as keep global xmin from advancing, so that the rows the cursor still needed to fetch would not get cleaned by VACUUM nor would the tables containing them get dropped or significantly altered. Either effect would be awful for performance if the cursor was held for long. Moreover, keeping the locks would effectively mean that the transaction wasn't really ended. So if that's what you want, don't commit the transaction. regards, tom lane
Tom>have to retain the locks held by the transaction
On 9-2-2018 23:09, Dave Cramer wrote: > Jaime, > > 9.4.1208 is considerably out of date. You may want to upgrade. The content of https://jdbc.postgresql.org/documentation/documentation.html suggests that the latest released documentation is for 9.4 (or at least, I always read HEAD as meaning latest development content). Maybe an idea to also add 42.x to that list? Mark > davec@postgresintl.com <mailto:davec@postgresintl.com> > www.postgresintl.com <http://www.postgresintl.com> > > On 8 February 2018 at 19:13, Brad DeJong <bpd0018@gmail.com > <mailto:bpd0018@gmail.com>> wrote: > > > > On Wed, Feb 7, 2018 at 1:00 PM, Jaime Soler <jaime.soler@gmail.com > <mailto:jaime.soler@gmail.com>> wrote: > > ... ResultSet holdability is HOLD_CURSOR_OVER_COMMIT. ... > And the postgresql comunity jdbc driver 9.4 documentation said: > "... There are a number of restrictions which will make the > driver silently fall back to fetch the whole ResultSet ..." -- Mark Rotteveel
On 9-2-2018 23:09, Dave Cramer wrote:Jaime,
9.4.1208 is considerably out of date. You may want to upgrade.
The content of https://jdbc.postgresql.org/documentation/documentation.html suggests that the latest released documentation is for 9.4 (or at least, I always read HEAD as meaning latest development content).
Maybe an idea to also add 42.x to that list?
Markdavec@postgresintl.com <mailto:davec@postgresintl.com>
www.postgresintl.com <http://www.postgresintl.com>
On 8 February 2018 at 19:13, Brad DeJong <bpd0018@gmail.com <mailto:bpd0018@gmail.com>> wrote:
On Wed, Feb 7, 2018 at 1:00 PM, Jaime Soler <jaime.soler@gmail.com
<mailto:jaime.soler@gmail.com>> wrote:
... ResultSet holdability is HOLD_CURSOR_OVER_COMMIT. ...
And the postgresql comunity jdbc driver 9.4 documentation said:
"... There are a number of restrictions which will make the
driver silently fall back to fetch the whole ResultSet ..."
--
Mark Rotteveel