13.3 シャーディングされたデータベースへの透過的アクセス用のシャーディング・データ・ソース

Oracle Databaseリリース21cでは、アプリケーションがシャーディング・キーを提供する必要なくシャード・データベースへのJava接続を可能にする、新しいJDBCデータ・ソースが導入されました。

シャード・データ・ソースを使用する場合、前の「シャーディング・キーを使用したプールからの接続のチェックアウト方法」の項で説明したように、シャード・データベースへの接続を確立するために、シャーディング・キーとスーパー・シャーディング・キーを識別したり、作成する必要はありません。シャーディング・データ・ソースでは、複数のシャード問合せ用に別のデータ・ソースを保持する必要もありません。

接続プロパティoracle.jdbc.useShardingDriverConnectiontrueに設定すると、このデータ・ソースはシャード・データベースに透過的にスケール・アウトされます。

次の表に、シャード・データ・ソースの使用方法を示します:

例13-2 シャーディング・データ・ソースの使用

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import oracle.jdbc.internal.OracleConnection;
import oracle.ucp.jdbc.PoolDataSource;
import oracle.ucp.jdbc.PoolDataSourceFactory;

public class ShardingDataSourceUCP {
    public static void main(String[] args) throws SQLException {
        ShardingDataSourceUCP sample = new ShardingDataSourceUCP();
        DataSource ucpDataSource = sample.getDataSource();
        // Get the details of following customers
        int[] customerIds = new int[] {
            100,
            101,
            102,
            103,
            104,
            105
        };

        for (int id: customerIds) {
            try (Connection conn = ucpDataSource.getConnection()) {
                sample.displayCustomerDetails(conn, id);
                System.out.println(((OracleConnection) conn).getPercentageQueryExecutionOnDirectShard());
            }
        }
    }

    private void displayCustomerDetails(Connection conn, int id) throws SQLException {
        try (PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM CUSTOMER where ID = ?")) {
            pstmt.setInt(1, id);
            try (ResultSet rs = pstmt.executeQuery()) {
                while (rs.next()) {
                    // Print the customer details
                }
            }
        }
    }

    private DataSource getDataSource() throws SQLException {
        PoolDataSource pds = PoolDataSourceFactory.getPoolDataSource();
        pds.setURL("<gsmURL>");
        pds.setUser("<userName>");
        pds.setPassword("<password>");
        pds.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");
        Properties prop = new Properties();
        // Connection property to enable sharding datasource feature, when this property
        // is set you don't need to pass sharding key to UCP pool while borrowing the connection
        prop.setProperty(OracleConnection.CONNECTION_PROPERTY_USE_SHARDING_DRIVER_CONNECTION, "true");
        pds.setConnectionProperties(prop);
        return pds;
    }
}

13.3.1 単一のシャード・トランザクションのサポート

シャーディング・データ・ソースを使用すると、トランザクションを1つのシャードに制限できます。

単一のシャード・トランザクションのサポートを有効にするには、CONNECTION_PROPERTY_ALLOW_SINGLE_SHARD_TRANSACTION_SUPPORTを設定する必要があります。このプロパティが設定されていない場合、デフォルトでは、すべてのトランザクションがシャード・カタログで起動されます。このプロパティの値をtrueに設定した場合、すべてのトランザクションが1つのシャードにのみまたがることを確認する必要があります。

例13-3 単一シャード・トランザクションの有効化

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import oracle.jdbc.internal.OracleConnection;
import oracle.jdbc.pool.OracleDataSource;

public class SingleShardTransactionUCP {
    public static void main(String[] args) throws SQLException {
        SingleShardTransactionUCP sample = new SingleShardTransactionUCP();
        DataSource ucpDS = sample.getDataSource();

        // Insert and update the details of following customers in a single transaction
        int[] customerIds = new int[] {
            100,
            101,
            102,
            103,
            104,
            105
        };

        for (int id: customerIds) {
            try (Connection conn = ucpDS.getConnection()) {
                conn.setAutoCommit(false);
                sample.insertCustomerDetails(conn, id);
                sample.displayCustomerDetails(conn, id);
                sample.updateCustomerDetails(conn, id);
                sample.displayCustomerDetails(conn, id);
                conn.commit();
                System.out.println(((OracleConnection) conn).getPercentageQueryExecutionOnDirectShard());
            }

        }
    }

    private void insertCustomerDetails(Connection conn, int id) throws SQLException {
        String sql = "insert into CUSTOMER values(?, ?, ?, ?)";
        try (PreparedStatement ps = conn.prepareStatement(sql)) {
            ps.setInt(1, id);
            ps.setString(2, name);
            ps.setString(3, email);
            ps.setString(4, phoneNumber);
            ps.executeUpdate();
        }
    }

    private void updateCustomerDetails(Connection conn, int id) throws SQLException {
        String sql = "UPDATE CUSTOMER SET name = ?, email = ?, phoneNumber = ? WHERE customerId = ?";
        try (PreparedStatement ps = conn.prepareStatement(sql)) {
            ps.setString(1, name);
            ps.setString(2, email);
            ps.setString(3, phoneNumber);
            ps.setInt(4, id);
            ps.executeUpdate();
        }
    }

    private void displayCustomerDetails(Connection conn, int id) throws SQLException {
        try (PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM CUSTOMER where ID = ?")) {
            pstmt.setInt(1, id);
            try (ResultSet rs = pstmt.executeQuery()) {
                while (rs.next()) {
                    //Print the customer details
                }
            }
        }
    }

    private DataSource getDataSource() throws SQLException {
        OracleDataSource ds = new OracleDataSource();
        ds.setURL( < gsmURL > );
        ds.setUser( < userName > );
        ds.setPassword( < password > );
        Properties prop = new Properties();
        //Connection property to enable sharding datasource feature
        prop.setProperty(OracleConnection.CONNECTION_PROPERTY_USE_SHARDING_DRIVER_CONNECTION, "true");

        //Connection property to enable single shard transaction support. If this property is not set, 
        // by default all the transactions are started on catalog DB. When setting this property value 
        // to "true", applications must ensure that all the transactions span over a single shard only.
        prop.setProperty(oracle.jdbc.OracleConnection.CONNECTION_PROPERTY_ALLOW_SINGLE_SHARD_TRANSACTION_SUPPORT, "true");
        ds.setConnectionProperties(prop);
        return ds;
    }
}