Size: a a a

2020 May 07

НБ

Никита Берегуля... in pro.jvm
источник

 P

 ‌‌Gleb Pilipets... in pro.jvm
Спасибо большое
источник

D

Dima in pro.jvm
@vladimirsitnikv Привет. Не подскажешь, pg jdbc неявно же открывает транзакцию при каждом селекте? И если я не делаю commit, драйвер сам неявно это делает?
источник

VP

Vladimir Petrakovich in pro.jvm
Dima
@vladimirsitnikv Привет. Не подскажешь, pg jdbc неявно же открывает транзакцию при каждом селекте? И если я не делаю commit, драйвер сам неявно это делает?
Мне кажется, или сама БД (почти?) всегда оборачивает каждый statement в тракзакцию, если её нет?
источник

KS

Kirill Shelopugin in pro.jvm
Продолжу вопрос, возник он отсюда: https://www.postgresql.org/docs/current/tutorial-transactions.html из фразы
PostgreSQL actually treats every SQL statement as being executed within a transaction. If you do not issue a BEGIN command, then each individual statement has an implicit BEGIN and (if successful) COMMIT wrapped around it. A group of statements surrounded by BEGIN and COMMIT is sometimes called a transaction block.Some client libraries issue BEGIN and COMMIT commands automatically, so that you might get the effect of transaction blocks without asking. Check the documentation for the interface you are using.
При этом в примерах JDBC -драйвера с выключенным autoCommit никто не делает никаких коммитов. https://jdbc.postgresql.org/documentation/head/query.html
Значит ли это, что, взяв из пула коннект, я могу сделать на нем 1000 селектов (без ручного коммита) и 1 апдейт (с ручным коммитом), и у меня не будет ситуации, когда на первом селекте началась транзакция, а закончилась только на апдейте?
источник

DP

Denis Pavlyuchenko in pro.jvm
можно же включить pg логи, и воспроизвести эту ситуацию (10000 селектов  + 1 апдейт), и увидеть, что update транзакция началась именно перед update запросом
источник

VP

Vladimir Petrakovich in pro.jvm
Kirill Shelopugin
Продолжу вопрос, возник он отсюда: https://www.postgresql.org/docs/current/tutorial-transactions.html из фразы
PostgreSQL actually treats every SQL statement as being executed within a transaction. If you do not issue a BEGIN command, then each individual statement has an implicit BEGIN and (if successful) COMMIT wrapped around it. A group of statements surrounded by BEGIN and COMMIT is sometimes called a transaction block.Some client libraries issue BEGIN and COMMIT commands automatically, so that you might get the effect of transaction blocks without asking. Check the documentation for the interface you are using.
При этом в примерах JDBC -драйвера с выключенным autoCommit никто не делает никаких коммитов. https://jdbc.postgresql.org/documentation/head/query.html
Значит ли это, что, взяв из пула коннект, я могу сделать на нем 1000 селектов (без ручного коммита) и 1 апдейт (с ручным коммитом), и у меня не будет ситуации, когда на первом селекте началась транзакция, а закончилась только на апдейте?
А мне больше интересно, как вот это (в https://jdbc.postgresql.org/documentation/head/query.html)
> The Connection must not be in autocommit mode. The backend closes cursors at the end of transactions, so in autocommit mode the backend will have closed the cursor before anything can be fetched from it.
вяжется с докой setAutoCommit():
> The commit occurs when the statement completes. The time when the statement completes depends on the type of SQL Statement:
> For Select statements, the statement is complete when the associated result set is closed.
источник

VP

Vladimir Petrakovich in pro.jvm
То есть если верить второму, транзакция не должна быть закрыта до закрытия ResultSet, а значит setAutoCommit(false) в примере с SELECT не нужен 🤔
источник

D

Dima in pro.jvm
Vladimir Petrakovich
То есть если верить второму, транзакция не должна быть закрыта до закрытия ResultSet, а значит setAutoCommit(false) в примере с SELECT не нужен 🤔
то есть закрытия резалтсета и коммитит неявную транзакцию?
источник

VP

Vladimir Petrakovich in pro.jvm
Dima
то есть закрытия резалтсета и коммитит неявную транзакцию?
Да, как я понял из javadoc
источник

VP

Vladimir Petrakovich in pro.jvm
Но это javadoc от JDBC, а ведёт ли себя так драйвер postgres - это отдельный вопрос
источник

VS

Vladimir Sitnikov in pro.jvm
Vladimir Petrakovich
То есть если верить второму, транзакция не должна быть закрыта до закрытия ResultSet, а значит setAutoCommit(false) в примере с SELECT не нужен 🤔
Одно не противоречит другому.

Попробую объяснить:
1) Если autocommit==true, то драйвер не делает обёртку begin … end. Дело в том, что одиночные запросы база сама обернёт в begin…end.
Результат она прилшлёт как набор строк (если есть). И все они будут засосаны в память (сколько есть)

2) Если же autocommit=false, то драйвер перед первым запросом добавит BEGIN и тем самым откроет транзакцию. Но база после каждого запроса возвращает текущий статус транзакции. Поэтому драйвер знает, что второй раз открывать не нужно.
источник

VP

Vladimir Petrakovich in pro.jvm
Vladimir Sitnikov
Одно не противоречит другому.

Попробую объяснить:
1) Если autocommit==true, то драйвер не делает обёртку begin … end. Дело в том, что одиночные запросы база сама обернёт в begin…end.
Результат она прилшлёт как набор строк (если есть). И все они будут засосаны в память (сколько есть)

2) Если же autocommit=false, то драйвер перед первым запросом добавит BEGIN и тем самым откроет транзакцию. Но база после каждого запроса возвращает текущий статус транзакции. Поэтому драйвер знает, что второй раз открывать не нужно.
Оно не противоречит, но такой пример запутывает немного
источник

L

Loljeene in pro.jvm
2) Но если транзакцию не закрыть, есть шанс отдать незакрытую транзакцию в пул соединений )
источник

VP

Vladimir Petrakovich in pro.jvm
Vladimir Petrakovich
Оно не противоречит, но такой пример запутывает немного
... и заставляет усомниться в том, что так всё и работает
источник

VP

Vladimir Petrakovich in pro.jvm
Loljeene
2) Но если транзакцию не закрыть, есть шанс отдать незакрытую транзакцию в пул соединений )
Ну нормальный пул должен быть готов к такому)
источник

VS

Vladimir Sitnikov in pro.jvm
Loljeene
2) Но если транзакцию не закрыть, есть шанс отдать незакрытую транзакцию в пул соединений )
Именно так. Поэтому правильные connection pool’ы должны либо warning выводить, либо транзакцию подчищать.

Если правильно помню, то , Weblogic делает rollback
источник

L

Loljeene in pro.jvm
Vladimir Sitnikov
Именно так. Поэтому правильные connection pool’ы должны либо warning выводить, либо транзакцию подчищать.

Если правильно помню, то , Weblogic делает rollback
мы в glassfish давно сами обертку над getConnection писали
источник

VS

Vladimir Sitnikov in pro.jvm
Vladimir Petrakovich
Оно не противоречит, но такой пример запутывает немного
Пример про вообще другую тему. Пример про то, чтобы обрабатывать 100500 строк и не упасть в OutOfMemoryError.

Теоретически, хочется, чтобы данные обрабатывались небольшими пачками. Например, чтобы каждый rs.next забирал очередную пачку из 1000 строк из базы и её обрабатывал.
И Oracle DB даже так по умолчанию работает, правда там размер пачки 10 штук )

Но в PostgreSQL так не работает, и чтобы «курсор» жил какое-то время нужно, чтобы была жива транзакция.

Поэтому setAutoCommit(false) в том примере нужно именно для того, чтобы заработал функционал «выбирать по 50 строк».

Кхм. ровно про это же недавно писал: https://habr.com/ru/post/499794/#comment_21566550


Там, конечно, есть второй вопрос: а почему мы транзакцию не закрываем. Технически, да, надо бы. Но в том конкретном примере, транзакция readonly, и закрывать нечего. Вообще нечего. База создаёт транзакцию только тогда, когда речь доходит до модификации данных (ну или хотя бы блокировки через select for update). Поэтому, после select’а, который как бы readonly, никакой транзакции остаться не может.

Но, да, наверное, логично было бы добавить commit, чтобы не смущать.
источник

VP

Vladimir Petrakovich in pro.jvm
Vladimir Sitnikov
Пример про вообще другую тему. Пример про то, чтобы обрабатывать 100500 строк и не упасть в OutOfMemoryError.

Теоретически, хочется, чтобы данные обрабатывались небольшими пачками. Например, чтобы каждый rs.next забирал очередную пачку из 1000 строк из базы и её обрабатывал.
И Oracle DB даже так по умолчанию работает, правда там размер пачки 10 штук )

Но в PostgreSQL так не работает, и чтобы «курсор» жил какое-то время нужно, чтобы была жива транзакция.

Поэтому setAutoCommit(false) в том примере нужно именно для того, чтобы заработал функционал «выбирать по 50 строк».

Кхм. ровно про это же недавно писал: https://habr.com/ru/post/499794/#comment_21566550


Там, конечно, есть второй вопрос: а почему мы транзакцию не закрываем. Технически, да, надо бы. Но в том конкретном примере, транзакция readonly, и закрывать нечего. Вообще нечего. База создаёт транзакцию только тогда, когда речь доходит до модификации данных (ну или хотя бы блокировки через select for update). Поэтому, после select’а, который как бы readonly, никакой транзакции остаться не может.

Но, да, наверное, логично было бы добавить commit, чтобы не смущать.
> Но в PostgreSQL так не работает, и чтобы «курсор» жил какое-то время нужно, чтобы была жива транзакция.
Так ведь она должна жить как раз до закрытия ResultSet, зачем отключать автокоммит?
источник