Могу ли я использовать один источник данных для нескольких баз данных с помощью Spring / Hibernate / c3p0? - PullRequest
4 голосов
/ 15 декабря 2011

Наше приложение использует Spring / Hibernate для доступа к базе данных. Мы используем несколько фабрик Hibernate (hibernate3.LocalSessionFactoryBean), потому что данные находятся в нескольких отдельных базах данных. Каждая фабрика сеансов конфигурируется с использованием пула данных с использованием c3p0 (c3p0.ComboPooledDataSource).

Как оказалось, все базы данных находятся на одном сервере БД. Наша проблема заключается в том, что мы получаем несколько пулов соединений db, подключающихся к одному и тому же серверу. Существует ли какой-либо способ совместного использования одного источника данных для доступа к нескольким базам данных на одном сервере? Можно ли настроить jdbcUrl на уровне фабрики сеанса, а не на уровне источника данных?

Или это не реальная проблема на практике? Это нормально, если настроено несколько пулов соединений с БД?

Ответы [ 2 ]

2 голосов
/ 16 декабря 2011

Одно соединение подключается к одной БД.

Если у вас есть две базы данных, DB1 и DB2, и вы хотите иметь пул соединений, вам необходимо подготовить соединения для обеих баз данных.

Если на самом деле у вас есть 1 соединение на пул, C1 и C2 (я знаю, что у вас больше, но это одно и то же ...) Наверняка можно было бы поместить эти оба соединения в один пул соединений.Тогда у вас будет пул соединений с C1 и C2.Что вы ожидаете от своего пула соединений?Для меня -> чтобы я мог дать вам случайное уже подготовленное соединение, которое вы можете использовать напрямую, без затрат на создание нового соединения.

Теперь угадайте, что, если у вас есть и С1, и С2 в вашем уникальном пулевы просто не можете получить «случайное» соединение, так как они не принадлежат одной и той же базе данных ... Таким образом, вам придется проверить, вернулось ли соединение к ожидаемой базе данных, или вы получите 50%шансы выполнить запрос R1 в DB2.

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

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


Для меня совершенно нормально иметь несколько пулов соединений в вашем приложении.Кроме того, совершенно нормально использовать 2 разные базы данных в одном приложении (Oracle + MongoDB или что-то в этом роде), также вполне нормально использовать 2 пула соединений, которые используют 2 схемы базы данных Oracle на одном сервере, и даже еслиобе базы данных имеют одинаковые таблицы.


Вы должны взглянуть на стратегии многопользовательского режима для приложений SaaS с несколькими клиентами (в целом B2B): - Одна из них - иметь одну БД для каждого клиента и иметь каждую таблицу.имеющий столбец "customer_id".Его проще обслуживать, но в таблицах больше строк (но, очевидно, вы индексируете этот столбец customer_id). Возможно, вы делаете другое: у вас есть одна база данных / источник данных / connectionpool / sessionfactory на каждого клиента, и каждая база данных будет иметь одинаковые таблицы,В конце концов у вас будет некоторый механизм, например, «настраиваемая основная сессионная фабрика», в которой будет использоваться ThreadLocal (установленный каким-либо фильтром учетных данных?), В котором хранится customerId для выбора соответствующей дочерней сессионной фабрики.

Посмотрите на следующеестатья для примера (есть много на эту тему): http://relation.to/Bloggers/MultitenancyInHibernate

public class MyTenantAwareConnectionProvider implements ConnectionProvider {
    public static final String BASE_JNDI_NAME_PARAM = "MyTenantAwareConnectionProvider.baseJndiName";

    private String baseJndiName;

    public void configure(Properties props) {
        baseJndiName = props.getProperty( BASE_JNDI_NAME_PARAM );
    }

    public Connection getConnection() throws SQLException {
        final String tenantId = TenantContext.getTenantId()
        final String tenantDataSourceName = baseJndiName + '/' + tenantId;
        DataSource tenantDataSource = JndiHelper.lookupDataSource( tenantDataSourceName );
        return tenantDataSource.getConnection();
    }

    public void closeConnection(Connection conn) throws SQLException {
        conn.close();
    }

    public boolean supportsAggressiveRelease() {
        // so long as the tenant identifier remains available in TL throughout, we can
        return true;
    }

    public close() {
        // currently nothing to do here
    }
}

Это почти то, что я вам сказал, за исключением того, что здесь есть поставщик динамического соединения вместо поставщика динамического сеанса.(Арендатор здесь = Клиент в моем примере)

Вы можете заметить, что в этом примере нет пула соединений, но вы уверены, что можете реализовать свой собственный PooledMyTenantAwareConnectionProvider;)

Удачи.

0 голосов
/ 15 декабря 2011

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

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

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

...