© 2007 Oracle Corporation€¦ · • Written in PHP: use OCI8 calls • All have similar basic...

Post on 21-Aug-2020

2 views 0 download

transcript

© 2007 Oracle Corporation

© 2007 Oracle Corporation

© 2007 Oracle Corporation

The Way to the Web with PHP and Oracle DatabaseChristopher Jones, Product Development, OracleOracle Develop, November 2007

© 2007 Oracle Corporation

The following is intended to outline our general

product direction. It is intended for information

purposes only, and may not be incorporated into any

contract. It is not a commitment to deliver any

material, code, or functionality, and should not be

relied upon in making purchasing decisions.

The development, release, and timing of any

features or functionality described for Oracle’s

products remain at the sole discretion of Oracle.

© 2007 Oracle Corporation

Overview

• About PHP and Oracle

• Using PHP's OCI8 extension

• Maximizing OCI8 performance

• PHP Applications

© 2007 Oracle Corporation

OCI8 Extension

© 2007 Oracle Corporation

What is OCI8?

<?php

$c = oci_connect('un', 'pw', '//localhost/XE');

$s = oci_parse($c, 'select * from employees');

oci_execute($s);

while ($row = oci_fetch_array($s))‏

foreach ($row as $item) ‏

print $item;

?>

• Main Oracle Database extension for PHP

• Open source and part of PHP

© 2007 Oracle Corporation

OCI8 Basic Oracle Features

• SQL and PL/SQL

• Long Objects (LOB), including Temporary LOBs

• Collections

• REFCURSORS

• Bind Data

• Change Password

• Privileged Connections

• Meta Data

© 2007 Oracle Corporation

OCI8 Performance Features

• Prefetch Rows

• Array Binds

• Statement Cache

• Fast Application Notification*

• With Oracle Database 11g• Server Result Cache

• Consistent Client Cache

• PL/SQL Function Cache

• Database Resident Connection Pooling*

* Support in PHP is currently Beta

© 2007 Oracle Corporation

Three Tier Web Model

Oracle Database8i, 9i, 10g, 11gAny platform

Web User Mid Tier9iR2, 10g, 11gAny platform

Apache

PHP

OCI8 ExtensionOracle Client Libraries

© 2007 Oracle Corporation

OCI8 Extension History

• Refactored by Oracle and Zend in 2005• Stable and fast

• In PHP 5.1.2+

• Same API as original OCI8 in PHP 3 and PHP 4

• New php.ini parameters for

• Persistent connection management

• Row prefetching

• Client side statement cache

• Enhanced OCI8 Beta released October 2007• Connection pooling support (DRCP) ‏

• High availability support (FAN) ‏

© 2007 Oracle Corporation

Get the Refactored OCI8

• php.net• Source code, Windows Binaries

• PECL - PHP Extension Community Library• Useful for updating PHP 4 with new OCI8

• Currently the only location of latest Beta OCI8

• oss.oracle.com/projects/php• RPMs for Linux with OCI8 and PDO_OCI

• Zend Core for Oracle• Linux, Solaris, Windows, AIX

• Support from Zend

© 2007 Oracle Corporation

Alternatives to OCI8

• ADOdb, PEAR MDB2, ...• Database Abstraction libraries

• Written in PHP: use OCI8 calls

• All have similar basic functionality

• PDO (PHP Data Objects) ‏• Data Access Abstraction

• Common and DB-specific calls

• Separate PHP Extension written in C

• Attracting interest, but not yet fully featured/stable

© 2007 Oracle Corporation

OCI8 Examples

© 2007 Oracle Corporation

SQL Statement Execution

• Parse - oci_parse() ‏

Prepares a statement for execution

• Bind - oci_bind_by_name() ‏

Optionally binds variables in WHERE clause or to PL/SQL arguments

• Execute - oci_execute() ‏

The Database executes the statement and buffers the results

• Fetch - oci_fetch_array() ‏

Optionally retrieves results from the database

© 2007 Oracle Corporation

Query Example

<?php

$c = oci_connect('hr','hrpwd','//localhost/XE');

$s = oci_parse($c, 'select last_name from employees');

oci_execute($s);

while ($row = oci_fetch_array($s)) ‏

foreach ($row as $item) ‏

print htmlentities($item).”<br>\n”;

?>

• Text file in $HOME/public_html/q.php

• Creates HTML page

© 2007 Oracle Corporation

Query Example

<?php

$c = oci_connect('hr','hrpwd','//localhost/XE');

$s = oci_parse($c,

'select last_name from employees');

oci_execute($s);

while ($row = oci_fetch_array($s)) ‏

foreach ($row as $item)‏

print htmlentities($item).”<br>\n”;

?>

© 2007 Oracle Corporation

Insert Example

<?php

$c = oci_connect('hr','hrpwd','//localhost/XE');

$s = oci_parse($c,

"insert into employees (last_name) values ('Jones')";

oci_execute($s);

?>

• Use single and double quotes carefully

• No output

© 2007 Oracle Corporation

Bind Variables

insert into tabvalues (:bv) ‏

insert into tab values (:bv)

insert into tab values (:bv) ‏

insert into tab values (:bv) ‏

1: insert into tab values (:bv) ‏

Database cacheIncreasesperformanceand security

© 2007 Oracle Corporation

No Bind Variables

insert into tabvalues (1) ‏

insert into tabvalues (2) ‏

insert into tab values (1) ‏

insert into tab values (2) ‏

1: insert into tab values (1) ‏2: insert into tab values (2) ‏

Database cache

Poor useof cache

© 2007 Oracle Corporation

Binding

• Associates PHP variable $name with the placeholder :bv

<?php

$c = oci_connect('hr','hrpwd','//localhost/XE');

$s = oci_parse($c,

'insert into employees (last_name) values (:bv)');

$name = 'Jones';

oci_bind_by_name($s, ':bv', $name);

oci_execute($s);

?>

© 2007 Oracle Corporation

Calling a PL/SQL Procedure

<?php

$c = oci_connect('hr','hrpwd','//localhost/XE');

$s = oci_parse($c, "begin myproc(1, 'Jones'); end;");

oci_execute($s);

?>

• No PHP output (empty page) ‏

© 2007 Oracle Corporation

Calling a PL/SQL Function

create or replace function

myfunc(p1 in number) return number as

begin

return 2 * p1;

end;

© 2007 Oracle Corporation

Calling a PL/SQL Function

<?php

$c = oci_connect('hr','hrpwd','//localhost/XE');

$s = oci_parse($c, 'begin :res := myfunc(1); end;');

oci_bind_by_name($s, ':res', $r, 10);

oci_execute($s);

print "Result is $r <br>\n";

?>

• Prints “Result is 2”

• Use a bind length for “out” bind return values

© 2007 Oracle Corporation

Commit Is Default

• By default oci_execute() commits

• Unnecessarily committing:• Breaks transactions

• Increases “round trips” to the database

• Increases database load

• String concatenation is insecure

$a = array('a','b','c','d');

foreach ($a as $v) {

$s = oci_parse($c,

"insert into mytab values ('".$v."')");

$r = oci_execute($s); // automatically commits

}

© 2007 Oracle Corporation

Using Transactions

$a = array('a','b','c','d');

$s = oci_parse($c, 'insert into mytab values (:bv)');

oci_bind_by_name($s, ':bv', $v);

foreach ($a as $v) {

oci_execute($s, OCI_DEFAULT); // Doesn't commit

}

oci_commit($c);

• OCI_DEFAULT is not the default in PHP!

• One parse, one commit

• No SQL Injection worry

© 2007 Oracle Corporation

Transactional Performance

• Representative sample for me

• Your results will vary

© 2007 Oracle Corporation

Connection Management

© 2007 Oracle Corporation

Connections

• Standard Connections$c = oci_connect($un, $pw, $db);

• Second oci_connect() returns same handle

• Automatically closed at script completion

• Can explicitly close

• Persistent Connections$c = oci_pconnect($un, $pw, $db);

• Second oci_pconnect() returns same handle

• Not automatically closed; cannot explicitly close

(Beta OCI8 does allow them to be released) ‏

© 2007 Oracle Corporation

Persistent Connections Cached

user:db:charset:privilegehr:XE:ALU32UTF8:normalsystem:XE:ALU32UTF8:sysdba

Second request fast

oci_pconnect()‏

© 2007 Oracle Corporation

Persistent Connections

$c = oci_pconnect($un, $pw, $db);

• Fast for subsequent connections• But holds database resources when application idle

• Configurable in php.inioci8.max_persistent

oci8.persistent_timeout

oci8.ping_interval

© 2007 Oracle Corporation

Maximum Number of Persistent Connections

• php.ini:oci8.max_persistent = -1

• Number of connections cached by each Apache process

• Using -1 means no limit

• If limit is reached, connections will succeed but will be treated like oci_connect() calls.

© 2007 Oracle Corporation

Timeout for Unused Persistent Connections

• php.ini:oci8.persistent_timeout = -1

• Seconds an idle connection will be retained

• Using -1 means no timeout

© 2007 Oracle Corporation

Round Trips Between PHP and Oracle

Round Trip

Tuning goal: minimize round trips

© 2007 Oracle Corporation

Pinging for Closed Persistent Connections

• php.ini:oci8.ping_interval = 60

• Seconds that pass before oci_pconnect() connection is checked before being used

• New connection created if old one unavailable

• Generates “round trip” to DB

• For scalability, disable by setting to -1• Applications need to recover from errors anyway

• With new Beta OCI8 use FAN events instead

© 2007 Oracle Corporation

Closing Connections

• An oci_close() closes connections from oci_connect() and oci_new_connect() (and oci_pconnect() with latest OCI8 Beta) ‏

• Unset related resources first $s = null;

oci_close($con);

• Closing is good in many circumstances, e.g.• Long running scripts with little DB interaction

• For connection pooling with latest OCI8 Beta

© 2007 Oracle Corporation

Database Resident Connection Pooling (DRCP)‏

• oci_connect() has performance overhead of connection creation/destroy

• oci_pconnect() has potential memory overhead of idle open connections

• PHP is multi-process; older pooling solutions are multi-threaded

• Oracle 11g introduces DRCP

• OCI8 1.3.0 Beta supports DRCP

© 2007 Oracle Corporation

Fast Application Notification

• High Availability feature for PHP with RAC or Data Guard with physical standby

• When DB node or network fails• Database generates FAN events

• PHP error returned without TCP timeout delay

• PHP application can reconnect to surviving instance

• OCI8 1.3.0 Beta supports FAN

© 2007 Oracle Corporation

Environment Setting

© 2007 Oracle Corporation

Pass the Character Set

$c = oci_pconnect($un, $pw, $db, 'ja16euc');

• Removes need for environment lookup

• Improves performance even for persistent connections

© 2007 Oracle Corporation

Connection Performance

• Representative sample for me

• Your results will vary

• Tune your SQL first

© 2007 Oracle Corporation

Optimize Environment Setting

• Could be improved

function my_connect($un, $pw, $db) ‏{$c = oci_pconnect($un, $pw, $db);$s = oci_parse($c, "alter session set

nls_date_format='YYYY-MM-DD HH24:MI:SS'");oci_execute($s);return $c;

}

© 2007 Oracle Corporation

Environment Setting: Process Environment

• Set NLS_DATE_FORMAT before starting Apache:$ export NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'

$ apachectl start

• PHP function now is:function my_connect($un, $pw, $db) ‏{

$c = oci_pconnect($un, $pw, $db);

return $c;

}

• All users get same format

• Application now depends on environment

© 2007 Oracle Corporation

Environment Setting: Trigger

• Use a PL/SQL LOGON trigger

create or replace trigger my_set_date

after logon on database

begin

if (user = 'HR') then

execute immediate

'alter session set nls_date_format =

''YYYY-MM-DD HH24:MI:SS'' ';

end if;

end my_set_date;

© 2007 Oracle Corporation

Environment Setting: Trigger

• PHP Code is

function my_connect($un, $pw, $db) ‏{

$c = oci_pconnect($un, $pw, $db);

return $c;

}

© 2007 Oracle Corporation

LOGON Trigger

• Fires only first time oci_pconnect() is called after Apache process starts• This is when the DB connection is created

• Subsequent oci_pconnect() calls get previously established connection from PHP cache• Trigger not executed

• Multiple SQL statements can be executed in the trigger• Reduces number of calls between PHP and DB

© 2007 Oracle Corporation

LOGON Trigger

• Measured PHP times, not DB load

• Representative results for me

• Your results will vary

© 2007 Oracle Corporation

Connections with Oracle RAC

• Tune auditing sequence generator

SQL> alter sequence sys.audses$ cache 10000;

• Reduces data transfers between nodes

• Also useful for non-RAC connection peaks

(RAC is “Real Application Clusters”) ‏

© 2007 Oracle Corporation

Statement Tuning

© 2007 Oracle Corporation

OCI8 Row Prefetching

$s = oci_parse($c,

'select location_id, city from locations');

oci_execute($s);

oci_set_prefetch($s, 100);

while ($row = oci_fetch_array($s))‏

foreach ($row as $item) ‏

print $item;

© 2007 Oracle Corporation

OCI8 Row Prefetching

Oracle Client Libraries

OCI8 Extension

1000, Roma

Database

1000, Roma1100, Venice1200, Tokyo. . .

PHP

Reduces round trips

oci_fetch_array()‏

Oracle Client Libraries

OCI8 Extension

1100, Venice 1000, Roma1100, Venice1200, Tokyo. . .

oci_fetch_array()‏

No DB access for next fetch

© 2007 Oracle Corporation

OCI8 Row Prefetching

• Set in the PHP script:

oci_set_prefetch($s, 100);

Or in php.inioci8.default_prefetch = 100

• Each database “round trip” prefetches lesser of:• 100 rows

• 100 * 1024 bytes

• Rows are cached internally by Oracle

• No need to change application

• No effect for REFCURSORS

© 2007 Oracle Corporation

OCI8 Row Prefetching

• Representative sample for me

• Your results will vary

© 2007 Oracle Corporation

Statement Caching: Client

select col from tab

select col from tab

select col from tab

“Use statement 1”

1: select col from tab

Database cache

1: select col from tab

Client cache

Less traffic and DB CPU

© 2007 Oracle Corporation

OCI8 Statement Cache

• php.inioci8.statement_cache_size = 20

• Unit is number of statements

• Client side cache of statements

• Moves cache management load from DB to PHP side

• Reduces net traffic and context switches

• Uses memory on PHP side for cached statement handles

• Uses memory on DB for per-session cursors

© 2007 Oracle Corporation

Limiting Data Transfers

• Don't fetch more data than necessary

• Use SQL to process data e.g. inline views, analytic functions, ...

• Oracle row limiting query is:

SELECT last_name FROM

(SELECT last_name,

ROW_NUMBER() OVER

(ORDER BY last_name) AS MYR

FROM employees)

WHERE MYR BETWEEN 11 and 20;

© 2007 Oracle Corporation

Bulk Inserts (PL/SQL Side)‏create or replace package mypkg as

type arrtype is table of varchar2(20) ‏

index by pls_integer;

procedure myproc(p1 in arrtype);

end mypkg;

create or replace package body mypkg as

procedure myproc(p1 in arrtype) is

begin

forall i in indices of p1

insert into mytab values (p1(i));

end myproc;

end mypkg;

© 2007 Oracle Corporation

Bulk Inserts (PHP Code)‏

$a = array('a', 'b', 'c', 'd');

$s = oci_parse($c, 'begin mypkg.myproc(:c1); end;');

oci_bind_array_by_name($s, ":c1", $a,

count($a), -1, SQLT_CHR);

oci_execute($s);

• Just three OCI8 calls

© 2007 Oracle Corporation

Insert Performance

• Representative sample for me

• Your results will vary

© 2007 Oracle Corporation

PHP Deployment

© 2007 Oracle Corporation

Alternative PHP Cache - APC

• PHP is interpreted (and mostly not thread safe) ‏• Each HTTP request reloads/parses scripts

• No data sharing between requests

• APC is a shared memory cache• Opcode cache for PHP scripts

• Can store user values

• Not distributed

• Opcode caches like APC are used by most sites

• Currently a PHP extension in PECL • Will be in PHP 6 by default

© 2007 Oracle Corporation

APC Opcode Cache

• Highly configurable e.g. php.ini settings• to minimize cache warm-up pains

• to filter which files are cached

• to not stat the file system for file updates

• to choose for type of locking

• and more

© 2007 Oracle Corporation

APC User values

$query = 'select * from employees';

$key = md5($query);

if (apc_fetch($key)) {return apc_fetch($key);

}else {$s = oci_parse($c, $query);oci_execute($s);oci_fetch_all($s, $res);$ser = serialize($res);apc_store($key, $ser);return $result;

}

© 2007 Oracle Corporation

Memcached

• Distributed object caching system

• Runs as a server

• PHP Memcache Extension provides interface• API is procedural or object style

© 2007 Oracle Corporation

PHP Memcache Extension

$memcache = new Memcache;$memcache->connect('memcache_host', 1111);

$query = 'select * from employees';$key = md5($query);if ($memcache->get($key)) {return $memcache->get($key);

}else {$c = oci_pconnect('hr', 'hrpwd', '//localhost/XE');$s = oci_parse($c, $query);oci_execute($s);oci_fetch_all($s, $res);$ser = serialize($res);$memcache->set($key, $ser, TRUE, 86400); // Store one dayreturn $result;

}

© 2007 Oracle Corporation

Oracle 11g Result Caches

• Oracle 11g has server and client result caches

• Caches are managed by Oracle• client cache is automatically invalidated by server changes

select /*+ result_cache */ * from employees

© 2007 Oracle Corporation

Rich Internet Applications with PHP

© 2007 Oracle Corporation

Rich Internet Applications

• Javascript libraries for RIAYahoo UI, Prototype/Scriptaculous, Dojo, ...

• Provide buttons, menus, calendars, sliders, ....

• Javascript libraries and CSS

• Not PHP• But PHP can generate HTML/Javascript content

• PHP can be target of XMLHttpRequest calls

• Tending to use JSON to transfer data to/from PHP

© 2007 Oracle Corporation

XMLHttpRequest<html>

<head>

<script type="text/javascript">

function makeRequest() ‏

{

httpRequest = new XMLHttpRequest();

httpRequest.open('GET', 'http://localhost:8888/~cjones/ajax1.php?somestuff');

httpRequest.onreadystatechange = function() ‏

{

if (httpRequest.readyState == 4) { alert(httpRequest.responseText); }

}

httpRequest.send(null);

}

</script>

</head>

<body onload="makeRequest()">

</body>

</html>

© 2007 Oracle Corporation

PHP Frameworks

© 2007 Oracle Corporation

PHP Frameworks

• Solar, CakePHP, Zend Framework, ...

• Provide standard way of building web applications and web services

• Allow rapid development• Scaffolding

• Are written in PHP

• Functionality includes• MVC, ActiveRecord, ACLs, helpers for AJAX, data

sanitization, request handling, ...

• DB support varies

© 2007 Oracle Corporation

Other PHP Sessions

• Scale Your PHP Application to Tens of Thousands of Connections• Connection Pooling, High Availability, Oracle Database 11g

Caching

• 1:45pm - 2:45pm, Hilton Continental Parlor 7 & 8

• Web 2.0 Applications Hands-on Lab with PHP and Oracle Database• Try PHP out yourself

• 1:45pm - 2:45pm, Hilton Continental Ballroom 4

© 2007 Oracle Corporation

The preceding is intended to outline our general

product direction. It is intended for information

purposes only, and may not be incorporated into any

contract. It is not a commitment to deliver any

material, code, or functionality, and should not be

relied upon in making purchasing decisions.

The development, release, and timing of any

features or functionality described for Oracle’s

products remain at the sole discretion of Oracle.

© 2007 Oracle Corporation

Oracle Technology Network PHP Developer Center

• Articles

• Install guides

• Underground PHP and Oracle Manual

• Online forum

• PHP RPMs

• Oracle JDeveloper 10g PHP extension

oracle.com/technology/php

© 2007 Oracle Corporation

Oracle Resources

• Oracle Techology Network (OTN) is freePHP Developer Center

www.oracle.com/technology/php

• Underground PHP and Oracle Manual• Articles, FAQs, links to blogs, JDeveloper PHP Extension,

PHP RPMs

• SQL and PL/SQL Questionsasktom.oracle.com

• Informationchristopher.jones@oracle.com

blogs.oracle.com/opal

• ISVs and hardware vendorsoraclepartnernetwork oracle com

© 2007 Oracle Corporation