7. April 2008

Schnellere Verbindungen zu Oracle11g: DBMS_CONNECTION_POOL

English title: Faster connections to Oracle11g: DBMS_CONNECTION_POOL)

Eine der weniger bekannten Eigenschaften von Oracle11g ist, dass sie einen neuen Connection-Pool mitbringt - und zwar den sogenannten Database Resident Connection Pool. Der Connection Pool wird also von der Datenbank selbst verwaltet. Die Frage liegt nahe, was das soll, denn Java oder .NET bringen bekanntlich ihre eigenen Connection Pools mit - wozu nun also einer in der Datenbank? Nun, primär wurde der Pool für PHP entwickelt - PHP ist von seiner Architektur her gar nicht in der Lage, einen eigenen Connection Pool zu haben - sobald ein PHP-Skript abgelaufen ist, werden alle Objekte zerstört. Um das Problem zu beheben, wird der Connection Pool von der Datenbank bereitgestellt ...
Oracle11g has brought many new features - some were dicussed very frequently and are therefore well known. Others are not so well-known - and one of these is the new Connection Pool: Database Resident Connection Pooling. This new connection pool is being maintained by the database engine itself. So people might ask, what's the purpose for this - since J2EE or .NET applications use their own connection pooling in most cases.
The answer is: PHP. This connection pool was primarily developed for PHP since PHP cannot have its own connection pool due to its architecture. When a PHP scripts ends all objects are destroyed - so a connection pool which would be shared by many PHP scripts cannot exist in the PHP architecture. Therefore the connection pool is provided by the database ...
Nun mögen manche einwerfen, dass das gar nicht neu ist - schließlich gibt es die Shared Server Architektur (auch als MTS - Multi Threaded Server bekannt) schon seit Oracle8i. Aber auch das wäre falsch, denn dieser neue Connection Pool enthält keine "shared" Server-Prozesse, welche mehrere Sessions bedienen können, sondern nur "dedicated" Server-Prozesse.
Perhaps this isn't new since Oracle has the Shared Server Architecture (also known as Multi-Threaded Server MTS) since Oracle8i. But in opposite to MTS this new connection pool contains dedicated, not shared server processes.
Was steckt also dahinter?
So what's behind this?
Der neue Database Resident Connection Pool dient dazu, "dedicated" Server-Prozesse "wiederzuverwenden" - wenn eine Datenbanksession also endet, wird der Server-Prozeß nicht zerstört, sondern nur "aufgeräumt" - die nächste Session bekommt dann den im Pool bereitstehenden Prozeß. Der Prozeß bleibt(!) dedicated - bis zu deren Ende bedient er ausschließlich diese Session. Für Speicherverwaltung gilt also das gleiche wie für "normale" Dedicated Server Prozesse (kein Wunder - es sind "normale" Dedicated Server-Prozesse).
The new Database Resident Connection Pool is for pooling and reusing dedicated server processes. When the database session ends the associated dedicated server process does not die - it will be cleaned up and placed back into the pool. If another database session is being initiated it gets its server process from the pool. Important: the server process stays dedicated - that means it will serve only one database session. Regarding the memory management the same rules as for "ordinary" dedicated server processes apply (the processes are "ordinary" dedicated server processes).
Und wozu kann man das brauchen, wenn man kein PHP programmiert?
I'm not programming PHP - so what is that good for?
Naja, mit dem neuen Connection Pool kann man bspw. schnellere SQL*Plus-Verbindungen bekommen - auch wenn der Pool in erster Linie für PHP entwickelt wurde, so kann man ihn doch beliebig nutzen - und der einfachste Weg (mit Default-Einstellungen) geht so:
Hmmm ... the new connection pool allows you to get faster SQL*Plus connections - the fact that the pool was primarily developed for PHP users does not prevent any other developer from using it. The most simple way to use the connection pool is as follows:
begin
  dbms_connection_pool.start_pool;
end;
Dieses Kommando startet den Connection Pool. Auch wenn die Prozeduren im Package vermuten lassen, dass man mehrere Pools in der Datenbank haben kann, so trifft das nicht zu - es kann nur einen (Connection Pool) geben. Mit der Prozedur DBMS_CONNECTION_POOL.CONFIGURE_POOL kann der Pool konfiguriert werden. Wenn man bei der Datenbankverbindung nun den Connection Pool nutzen möchte, muss man das einfach beim TNS-Connection-String angeben (dieses Beispiel nutzt die easy connect syntax):
This command starts the connection pool. The procedures in the package let assume that there can be multiple connection pools with different settings in the database - but this is not true: there can only be one (connection pool). The procedure DBMS_CONNECTION_POOL.CONFIGURE_POOL allows to change the pool configuration. To use the pool when connection to a database instance one has only to supply a keyword in the TNS connection string (this example uses the easy connect syntax).
$ sqlplus scott/tiger@database-host:1521/service-name:POOLED
Probiert es aus: Spätestens beim zweiten Mal geht es schneller - einfach weil die Datenbank keinen neuen Serverprozeß mehr starten muss. Und obwohl der Connection Pool in Java nicht nötig ist (Connection Pools für Java gibt es reichlich), lässt sich der Unterschied mit dem folgenden Java-Programm sehr überzeugend darstellen.
Just give it a try: At least with the second connect you should experience a faster connection - just because the database has not to explicitly start the server process. And although the connection pool is not needed for java (java programmers can choose between a bunch of connection pools), the following java program shows the very difference between using and not using the pool.
import java.sql.*;

public class ConnPoolTest {

  static long lTimeStart;

  public static void main(String args[]) throws Exception {
    DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
    Connection con = null;

    lTimeStart = System.currentTimeMillis();
    System.out.println("*** Start: going to connect 50 times ...");
    System.out.println("*** ... 1st: without \"database resident connection pool\":");
    for (int i=0;i<50;i++) {
      con = DriverManager.getConnection(
        "jdbc:oracle:oci8:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))(CONNECT_DATA = (SERVICE_NAME=orcl.doag.org)))","scott","tiger"
      );
      System.out.print(".");
      con.close();
    }
    System.out.println("*** time elapsed: " +(System.currentTimeMillis() - lTimeStart)+"ms.");
    lTimeStart = System.currentTimeMillis();
    System.out.println("*** ... 2nd: WITH \"database resident connection pool\":");
    for (int i=0;i<50;i++) {
      con = DriverManager.getConnection(
        "jdbc:oracle:oci8:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))(CONNECT_DATA = (SERVICE_NAME=orcl.doag.org)(SERVER=POOLED)))","scott","tiger"
      );
      System.out.print(".");
      con.close();
    }
    System.out.println("*** time elapsed: " +(System.currentTimeMillis() - lTimeStart)+"ms.");
  }
}
Starten ...
Start it ...
$ java ConnPoolTest
*** Start: going to connect 50 times ...
*** ... 1st: without "database resident connection pool":
..................................................
*** time elapsed: 25410ms.

*** ... 2nd: WITH "database resident connection pool":
..................................................
*** time elapsed: 1477ms.

$
25 Sekunden vs 1.5 Sekunden - das ist schon ein Unterschied! Beachtet dabei aber, dass dazu ein 11g-Client nötig ist (nur der kann das Schlüsselwört POOLED richtig an den Datenbankserver übergeben). Und beim Java-Programm war natürlich der 11g OCI-Treiber vonnöten.
25 vs 1.5 seconds - that's a difference! But note that an 11g Client is required (earlier clients cannot communicate the "pooled connection request" to the database server). And for the java program (of course) the 11g OCI driver was needed.

Keine Kommentare:

Beliebte Postings