Запуск PostgreSQL только в памяти



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



@Before
void setUp() {
String port = runPostgresOnRandomPort();
connectTo("postgres://localhost:"+port+"/in_memory_db");
// ...
}


В идеале у меня будет один исполняемый файл postgres, проверенный в системе управления версиями, который будет использовать модульный тест.



что-то вроде HSQL, но для postgres. Как я могу это сделать?



могу ли я получить такую версию Postgres? Как я могу проинструктировать его не использовать диск?

796   6  

6 ответов:

Это невозможно с Postgres. Он не предлагает в процессе/в памяти двигателя, как HSQLDB или MySQL.

Если вы хотите создать автономную среду вы можете поместите двоичные файлы Postgres в SVN (но это больше, чем просто один исполняемый файл).

вам нужно будет запустить initdb чтобы настроить тестовую базу данных, прежде чем вы сможете что-либо сделать с этим. Это можно сделать из пакетного файла или с помощью среды выполнения.выполнение.)( Но учтите, что initdb-это не то, что быстро. Вы определенно не захотите запускать это для каждого теста. Однако вы можете уйти, запустив это перед своим тестовым набором.

однако, хотя это можно сделать, я бы рекомендовал иметь специальную установку Postgres, где вы просто воссоздаете свою тестовую базу данных перед запуском тестов.

вы можете повторно создать тестовую базу данных с помощью шаблона базы данных, что делает его создание довольно быстро (a много быстрее, чем работает initdb для каждого тестового запуска)

или вы могли бы создать пространство в ramfs / tempfs и создать все ваши объекты там.
Недавно мне указали на статья о том, чтобы делать именно это на Linux.

предупреждение

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

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

(перемещая мой ответ от использование в памяти PostgreSQL и обобщая ее):

вы не можете запустить Pg in-process, in-memory

я не могу понять, как запустить базу данных Postgres в памяти для тестирования. Возможно ли это?

нет, это невозможно. PostgreSQL реализован на языке C и скомпилирован в код платформы. В отличие от H2 или дерби вы не можете просто загрузить jar и запустить его как выброс в памяти ДЕЦИБЕЛ.

в отличие от SQLite, который также написан на C и скомпилирован в код платформы, PostgreSQL также не может быть загружен в процессе. Это требует нескольких процессов (по одному на соединение), потому что это многопроцессорная, а не многопоточная архитектура. Требование многопроцессорной обработки означает, что вы должны запустите postmaster как автономный процесс.

вместо этого: предварительно настроить соединение

я предлагаю просто писать тесты, чтобы ожидать конкретное имя/логин/пароль для работы и тестирования CREATE DATABASE одноразовая база данных, затем DROP DATABASE в конце прогона. Узнать детали подключения к базе данных из файла свойств, строить целевые свойства, переменные среды и т. д.

безопасно использовать существующий экземпляр PostgreSQL, в котором у вас уже есть базы данных, о которых вы заботитесь, если пользователь, которого вы предоставляете своим модульным тестам,не суперпользователь, только пользователь с CREATEDB прав. На в худшем случае вы создадите проблемы с производительностью в других базах данных. По этой причине я предпочитаю запускать полностью изолированную установку PostgreSQL для тестирования.

вместо этого: запустите одноразовый экземпляр PostgreSQL для тестирования

если вы действительно Кин, вы могли бы пусть ваш тестовый жгут найдет initdb и postgres файлы, запустите initdb создать базу данных, изменить pg_hba.conf до trust, используя postgres чтобы запустить его на случайном порту, создайте пользователь, создайте БД и запустите тесты. Вы даже можете объединить двоичные файлы PostgreSQL для нескольких архитектур в jar и распаковать их для текущей архитектуры во временный каталог перед запуском тестов.

лично я думаю, что это серьезная боль, которую следует избегать; это намного проще просто настроить тестовую БД. Тем не менее, это стало немного легче с появлением include_dir поддержка в postgresql.conf, теперь вы можете просто добавить одну строку, а затем написать сгенерированный конфигурационный файл для всех остальных.

более быстрое тестирование с помощью PostgreSQL

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

диалект PostgreSQL H2 не является истинной заменой

некоторые люди вместо этого используют базу данных H2 в режиме диалекта PostgreSQL для запуска тесты. Я думаю, что это почти так же плохо, как люди Rails, использующие SQLite для тестирования и PostgreSQL для развертывания производства.

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

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

табличные пространства-это не ответ!

Do не используйте табличное пространство для создайте базу данных "в памяти". Это не только не нужно, так как это не поможет производительности значительно в любом случае, но это также отличный способ нарушить доступ к любому другому, о котором вы могли бы заботиться в той же установке PostgreSQL. документация 9.4 теперь содержит следующее предупреждение:

предупреждение

несмотря на то, что находится за пределами основного каталога данных PostgreSQL, табличные пространства являются неотъемлемой частью кластера баз данных и не может быть рассматривается как автономный набор файлов данных. Они зависимы на метаданные, содержащиеся в основном каталоге данных, и поэтому не могут подключается к другому кластеру баз данных или создается резервная копия отдельно. Аналогично, если вы потеряете табличное пространство (удаление файла, сбой диска, etc), кластер баз данных может стать нечитаемым или не может быть запущен. Размещение табличного пространства во временной файловой системе, такой как ramdisk, рискует надежность всего группа.

потому что я заметил, что слишком много людей делают это и сталкиваются с проблемами.

(если вы сделали это вы можете mkdir отсутствует каталог табличного пространства, чтобы получить PostgreSQL, чтобы начать все сначала, а затем DROP отсутствующих баз данных, таблиц и т. д. Лучше просто не делать этого.)

теперь можно запустить экземпляр PostgreSQL в памяти в ваших тестах JUnit с помощью встроенного компонента PostgreSQL из OpenTable:https://github.com/opentable/otj-pg-embedded.

путем добавления зависимости в библиотеку otj-pg-embedded (https://mvnrepository.com/artifact/com.opentable.components/otj-pg-embedded) Вы можете запустить и остановить свой собственный экземпляр PostgreSQL в ваших @Before и @ Afer крючках:

EmbeddedPostgres pg = EmbeddedPostgres.start();

Они даже предложите правило JUnit для автоматического запуска и остановки вашего сервера базы данных PostgreSQL для вас:

@Rule
public SingleInstancePostgresRule pg = EmbeddedPostgresRules.singleInstance();

вы могли бы использовать TestContainers чтобы развернуть контейнер PosgreSQL docker для тестов: http://testcontainers.viewdocs.io/testcontainers-java/usage/database_containers/

TestContainers обеспечивают JUnit @Rule / @ClassRule: этот режим запускает базу данных внутри контейнера перед вашими тестами и затем разрывает ее.

пример:

public class SimplePostgreSQLTest {

    @Rule
    public PostgreSQLContainer postgres = new PostgreSQLContainer();

    @Test
    public void testSimple() throws SQLException {
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setJdbcUrl(postgres.getJdbcUrl());
        hikariConfig.setUsername(postgres.getUsername());
        hikariConfig.setPassword(postgres.getPassword());

        HikariDataSource ds = new HikariDataSource(hikariConfig);
        Statement statement = ds.getConnection().createStatement();
        statement.execute("SELECT 1");
        ResultSet resultSet = statement.getResultSet();

        resultSet.next();
        int resultSetInt = resultSet.getInt(1);
        assertEquals("A basic SELECT query succeeds", 1, resultSetInt);
    }
}

вы также можете использовать параметры конфигурации PostgreSQL (например, те, которые подробно описаны в вопросе и принятом ответе здесь) для достижения производительности без необходимости прибегать к базе данных в памяти.

Comments

    Ничего не найдено.