Предотвращение внедрения SQL без подготовленных операторов (JDBC) - PullRequest
4 голосов
/ 06 августа 2009

У меня есть приложение для журнала базы данных, которое время от времени вставляет в базу данных переменное число строк журнала.

Я хотел бы создать оператор SQL таким образом, чтобы предотвратить внедрение SQL, но не использовать подготовленные операторы на стороне сервера (поскольку у меня есть переменное число строк в каждом выборе, их кэширование не поможет, но может повредить производительность здесь).

Мне также нравится удобство подготовленных отчетов, и я предпочитаю их конкатенации строк. Есть ли что-то вроде «подготовленного клиентом заявления»?

Ответы [ 6 ]

7 голосов
/ 06 августа 2009

Похоже, вы еще не протестировали самое простое решение - подготовленные заявления. Вы говорите, что они «могут ухудшить производительность», но пока вы не протестируете это, вы действительно не будете знать.

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

Зачем тратить время на поиски альтернативных решений, если вы еще не попробовали самое очевидное?

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

2 голосов
/ 06 августа 2009

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

Я не думаю, что ваши проблемы с производительностью неуместны. Я, конечно, видел, как предварительно скомпилированные сложные операторы резко терпели неудачу в масштабе производительности (в MS-SQL 2000). Причина в том, что оператор был настолько сложным, что в нем было несколько возможных путей выполнения в зависимости от параметров, но компиляция блокировала один для одного набора параметров, а следующий набор параметров был слишком медленным, тогда как перекомпиляция приводила бы к пересчету план выполнения больше подходит для другого набора параметров.

Но это беспокойство очень далеко, пока вы не увидите его на практике.

Основная проблема здесь заключается в том, что экранирование параметров зависит от конкретной базы данных, поэтому, если драйвер JDBC для вашей базы данных не даст вам чего-то нестандартного для этого (весьма маловероятно), вам понадобится другая библиотека или другая механизм экранирования, который очень специфичен для этой базы данных.

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

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

Из спецификации:

Оператор SQL с параметрами IN или без них можно предварительно скомпилировать и сохранить в объекте PreparedStatement. Этот объект затем может быть использован для эффективного выполнения этого оператора несколько раз.

2 голосов
/ 06 августа 2009

Не уверен, правильно ли я понимаю ваш вопрос. Есть ли в PreparedStatement что-то, что не соответствует вашим потребностям?

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

0 голосов
/ 06 августа 2009

Подготовленные отчеты не заботятся о клиенте или сервере.

Используйте их и отбросьте любую конкатенацию строк SQL. Нет ни одной причины не использовать подготовленные отчеты.

0 голосов
/ 06 августа 2009

Я не могу придумать причину, почему вы не должны использовать подготовленные заявления. Если вы выполняете это на сервере J2EE с помощью пула соединений, сервер сохраняет ваши соединения открытыми, и сервер кэширует ваши планы доступа / выполнения. Это не данные, которые он кеширует!

Если вы закрываете свое соединение каждый раз, то вы, вероятно, не получаете никакой производительности. Но вы все равно получаете предотвращение внедрения SQL

Большинство книг по настройке производительности Java скажут вам то же самое: Настройка производительности Java

0 голосов
/ 06 августа 2009

что не так с использованием регулярного подготовленного заявления, например в следующем псевдокоде:

DatabaseConnection connection;
PreparedStatement insertStatement = ...;

    ...

connection.beginTransaction();
for (Item item : items)
{
   insertStatement.setParameter(1, item);
   insertStatement.execute();
}
connection.commitTransaction();

Интеллектуальная реализация базы данных объединит несколько вставок в один обмен данными с сервером базы данных.

...