JDBC - setAutoCommit для операции только для чтения

Допустим, у меня есть общий метод, который создает соединение с БД:

Connection getConnection() throws SQLException {
    Connection con = ... // create the connection
    con.setAutoCommit(false);
    return con;
}

Я положилsetAutoCommit(false) вызовите здесь так, чтобы вызывающие этого метода никогда не беспокоились о его настройке. Однако является ли это плохой практикой, если операция, выполняемая вызывающей стороной, только читает данные? Есть ли дополнительные накладные расходы?

Мое личное мнение заключается в том, что лучше централизовать логику в одном месте, так что вызывающим абонентам никогда не придется устанавливать автоматическую фиксацию, и это позволяет избежать избыточности кода. Я просто хотел убедиться, что это не повлечет за собой ненужные накладные расходы для операции только для чтения.

Ответы на вопрос(4)

SELECT запросы. Но отключение автоматической фиксации действительно более распространенная практика. Более часто вы хотели бы запускать запросы в транзакции. Большинство пулов соединений также по умолчанию отключает его. Однако я бы предложил сделать его настройкой конфигурации вашего диспетчера соединений и / или перегрузить метод, принимая логический аргумент, чтобы вы по крайней мере имелилюбой контроль над этим на случай, что.

 beldaz19 июн. 2015 г., 02:18
@BalusC Aselect Запрос может вводить общие блокировки или требовать дополнительных копий кортежей чтения на время транзакции (в зависимости от уровня изоляции). Разве вы не сказали бы, что означает автокоммитделает иметь значение дляselect запросы?

нижение производительности, если вообще что-либо, ничто по сравнению с побочными эффектамиautocommit=true подключение.

Вы говорите, что никогда не будете использовать это соединение для DML. Но этонамерениевозможно, поддерживается стандартами кодирования и т. д. Но на практике этоявляется Можно использовать это соединение для операторов DML. Это достаточная причина для меня, чтобы никогда не включать автоматическую фиксацию.

Select операторы определенно собираются занять немного памяти / процессора / сети. Пусть накладные расходы на автоматическую фиксацию будут (очень незначительными) фиксированными накладными расходами для каждого оператора select, чтобы обеспечить целостность данных и стабильность вашего приложения.

Решение Вопроса

чтобы вызывающие его методы никогда не беспокоились о его настройке.

Это хорошая IMO, и я лично считаю, что никогда не следует включать режим автоматической фиксации внутри приложения. Поэтому я рекомендую отключить автоматическую фиксацию.

Однако является ли это плохой практикой, если операция, выполняемая вызывающей стороной, только читает данные? Есть ли дополнительные накладные расходы?

С точки зрения строгой производительности, он запускает и завершает транзакцию базы данных для каждого оператора SQL, который имеет накладные расходы и может снизить производительность вашего приложения.

Кстати, на операторы SELECT влияютsetAutoCommit(boolean) в соответствии с Javadoc:

Устанавливает режим автоматической фиксации этого соединения в заданное состояние.Если соединение находится в режиме автоматической фиксации, все его операторы SQL будут выполняться и фиксироваться как отдельные транзакции., В противном случае его операторы SQL группируются в транзакции, которые завершаются вызовом метода commit или отката метода. По умолчанию новые подключения находятся в режиме автоматической фиксации.

Фиксация происходит, когда инструкция завершается. Время завершения оператора зависит от типа оператора SQL:

Для операторов DML, таких как операторы Insert, Update или Delete и DDL, оператор завершается, как только он завершил выполнение.Для операторов Select оператор завершается, когда связанный набор результатов закрыт.Для объектов CallableStatement или для операторов, которые возвращают несколько результатов, оператор завершается, когда все связанные наборы результатов были закрыты, и все значения обновления и выходные параметры были получены.
 beldaz19 июн. 2015 г., 02:15
Я не согласен с вопросом производительности начальных и конечных транзакций. Это никогда не было моим опытом, скорее, несколько длинных транзакций вызывают больше узких мест, чем множество мелких. Есть ли у вас доказательства обратного?

Спектакль

Снижение производительности от транзакций зависит от механизма управления параллелизмом: обычно многоуровневое управление параллелизмом или блокировка. Озабоченность, выраженная в других ответах, по-видимому, связана со стоимостью завершения транзакции, но, по моему опыту, самая большая проблема - это длительные транзакции, которые могут стать причиной узких мест производительности. Например, если СУБД использует блокировку, некоторые части таблицы не могут быть обновлены, пока транзакция с этой таблицей не будет завершена. Больше разочаровывает в системах, таких как Oracle, что операции DDL (ALTER TABLEи т. д.) должны дождаться завершения всех транзакций, использующих эту таблицу, что приведет к хлопотным тайм-аутам. Так что не думайте, что ваша транзакция не имеет штрафов, если вы просто используетеSELECTs.

Условные обозначения

Тонкая проблема с отключением режима автоматической фиксации заключается в том, что вы переходите от значения по умолчанию, поэтому любой, кто работает с вашим кодом, может этого не ожидать. этодействительно легко оставить случайный путь через функцию, которая не заканчивается явнымcommit или жеrollback, и это может привести к непредсказуемому поведению в последующих вызываемых функциях. И наоборот, большая часть кода взаимодействия с БД, который я видел, содержит один оператор в каждой функции, для которого очень хорошо подходит поведение автоматической фиксации. Фактически, многие функции с несколькими утверждениями, с которыми я сталкивался, могли быть переписаны как отдельные операторы с немного большим ноу-хау в SQL - к сожалению, плохое приближение к объединениям, реализованным в Java, является обычным явлением.

Мои личные предпочтения, основанные на разумном опыте, заключаются в следующем для любых функций, выполняющих вызовы в базу данных:

придерживаться стандартного поведения JDBC при автоматической фиксации;если ваша функция включает более одного оператора SQL, используйте явную транзакцию, установивsetAutocommit(false) в начале каждой функции и вызоваcommit() (или жеrollback() если уместно) в конце и в идеалеrollback() вcatch блок;обеспечить соблюдение по умолчанию, поставивsetAutocommit(true) вfinally блок, который оборачивает ваши вызовы JDBC в функцию (в отличие от таких API, как PHP / PDO, JDBC не сделает этого за вас послеcommit()/rollback());если вы чувствуете себя более оборонительным, четко установите свой выборsetAutocommit(true) или жеsetAutocommit(false) в начале каждой функции;
 Tom Dibble24 июн. 2015 г., 17:31
dcp - предоставленная вами ссылка Ask Tom не предоставляет никаких причин для отключения автоматической фиксации, за исключением того, что титульный Том называет это "глупым". Есть ли какая-то реальная причина? Возможно, другая статья о том, где он отмечает некоторые проблемы с производительностью или функциональностью краткосрочных транзакций?
 beldaz21 июн. 2015 г., 23:28
@dcp Зависит от того, насколько хорошо вы понимаете транзакции. Многие люди этого не делают, но по-прежнему пишут код для работы с базами данных (вспомним все лампочки, стоящие там, и весь код оболочки, как в Ruby, который скрывает транзакционное поведение). Автоматическая фиксация позволяет избежать пагубных ошибок операторов, которые появляются, но не сохраняются между сессиями.
 dcp02 июл. 2015 г., 15:03
@Tom Dibble - вот еще одна ссылка от Asktom:asktom.oracle.com/pls/apex/...  Если вы прокрутите примерно наполовину вниз, вы увидите комментарии Тома: «Вы всегда должны завершать свою собственную работу - вы должны явно фиксировать или откатывать на основе ВАШЕЙ логики. Никогда не полагайтесь на окружение, чтобы сделать это, это может сделать что-то другое». Суть в том, что транзакции представляют собой единицу работы, которую клиент упаковывает вместе, поэтому клиент должен определить, когда эта работа будет зафиксирована.
 dcp22 июн. 2015 г., 01:28
Я не могу спорить с вами там, потому что отсутствие понимания базы данных, безусловно, проблема. Я знаю, когда мы проводим интервью с людьми, они могут знать .Net / Java / независимо от языка / и т.д. очень хорошо, но попросите их написать простую инструкцию SQL или объяснить уровни изоляции транзакции, и они не знают, как на это ответить. Я вижу это как большую проблему, потому что реляционные базы данных по-прежнему являются ключевыми, и люди должны понимать, как их использовать. Вот почему я стою, отключив автоматическую фиксацию, ожидая большего от разработчиков и заставляя их не полагаться на инструменты.
 dcp21 июн. 2015 г., 14:13
«придерживаться стандартного поведения JDBC при автоматической фиксации» - не совсем согласен с таким подходом. Я всегда отключаю его при написании кода Java, вы можете обратиться сюда по причинам, почему:asktom.oracle.com/pls/asktom/...  Даже для транзакции с одним оператором яснее оставить ее отключенной и позволить клиентскому коду иметь полный контроль над транзакцией.

Ваш ответ на вопрос