© 2008 Oracle Corporation

© 2008 Oracle Corporation
<Insert Picture Here>
PHP: Build and Deploy Mission Critical Applications
with Oracle Database 11g
Luxi Chidambaran, Architect, Oracle
NoCOUG Spring Conference
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.
© 2008 Oracle Corporation
Overview
• What is PHP?
• Connecting PHP to Oracle: The OCI8 Extension
• Massive Connection Scalability
• OCI8 Best Practices
• Client Result Cache
• Tracing and Monitoring
• High Availability
• In the News
© 2008 Oracle Corporation
What is PHP?
© 2008 Oracle Corporation
What is PHP?
• Dynamically typed, open-source, scripting language
• Rich functionality
• Large number of extensions/interfaces
• Commonly generates HTML output
• Dynamic web pages
• Widely Used
• PHP is in Tiobe's top 5 languages
(Statistics: www.tiobe.com)
© 2008 Oracle Corporation
Hello World!
<!DOCTYPE html>
<html>
<head>
<title>PHP Test</title>
</head>
<body>
<?php
echo 'Hello World';
?>
</body>
</html>
© 2008 Oracle Corporation
Connecting PHP to
Oracle: The OCI8
Extension
© 2008 Oracle Corporation
What is OCI8?
• Main Oracle Database extension for PHP
• Open source and part of PHP
<?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;
?>
© 2008 Oracle Corporation
Three Tier Web Model
Apache
PHP
OCI8 Extension
Oracle Client
Libraries
Web User
© 2008 Oracle Corporation
Mid Tier
9iR2, 10g, 11g
Oracle Client
Any platform
Oracle Database
9i, 10g, 11g
Any platform
PHP OCI8 Features
• Execute SQL and PL/SQL
• LOBs, including Temporary LOBs
• Collections
• REF CURSORS
• Binds and Array Binds
• Persistent Connections
• Prefetching
• Statement Caching
• Meta Data
• Password Changing
• TimesTen!
© 2008 Oracle Corporation
Getting PHP OCI8 1.4.5
• php.net
• PHP 5.3 Source code, Windows binaries
• PECL - PHP Extension Community Library
• For updating PHP 4.3.9+ with latest OCI8
• http://oss.oracle.com/projects/php
• RPMs for Linux with OCI8
• Unbreakable Linux Network
• Oracle's Linux Support program
• OCI8 RPM available for PHP
• Zend Server
• Linux, Windows, Mac
• Support from Zend
© 2008 Oracle Corporation
PHP OCI8 Extension for Oracle
Database
• Windows DLLs available with PHP
• Linux install with
$ configure … --with-oci8=instantclient,$HOME/instantclient_11_2
or
$ pecl install oci8
...
Please provide the path . . . :
instantclient,/home/lchidamb/instantclient_11_2
• Included in Zend Server
© 2008 Oracle Corporation
Standard OCI8 connections
• $c = oci_connect($un, $pw, $db);
• Connection exists for script life
• Subsequent oci_connect() in a script returns same DB
connection
• High Overhead
• Connection establishment on first call in script
• Connection teardown at end of script
• Huge scaling issue
© 2008 Oracle Corporation
Persistent OCI8 Connections
•
$c = oci_pconnect($un, $pw, $db);
• Not automatically closed at end of script
• Fast for subsequent connections
• Holds resources when application idle
• Second oci_pconnect() in script returns same
connection
• Some control configurable in php.ini
•
oci8.max_persistent
• Number of connections per PHP process
•
oci8.persistent_timeout
• “Idle” expiry time
•
oci8.ping_interval
• Ping after retrieving from PHP cache
© 2008 Oracle Corporation
Massive Connection
Scalability
© 2008 Oracle Corporation
Massive Connection Scalability
• Use Non Persistent Connections?
• High connect times
• Burns CPU
• Not scalable
• Use Persistent Connections?
• Majority idle
• Excessive swapping, eventually exhausts RAM
• Neither strategy really works at O(a few thousand)
database connections
• Of course, you could throw more hardware at it
• Poor utilization of system resources
• Poor utilization of $$
© 2008 Oracle Corporation
Database Resident Connection Pool
• Oracle Database 11g Feature
• Not just for PHP
• Pool of dedicated servers on database machine
• Pool shared across mid-tier processes and middle-tier
nodes
• Scales to tens of thousands of persistent connections
• Speeds up non-persistent connections
• Co-exists in all database server configurations
• Single instance, RAC
© 2008 Oracle Corporation
Basic Functionality
• Pooling is optionally enabled by DBA on server
• Min, Max, Timeout etc. for Pool
• Client connect string:
• hostname/service:POOLED
• (SERVER=POOLED)
• Client directed to Database Resident Pool
• Pooled Server “locked” when connection requested
by client
• Pooled Server “released” back to pool when client
disconnects
© 2008 Oracle Corporation
Dedicated Servers vs DRCP
No Connection Pooling
© 2008 Oracle Corporation
11g Database Resident Connection Pooling
Sample Sizing for 5000 Clients
Database
Servers
Session
Memory
Dedicated
Servers
Shared
Servers
DRCP
Servers
5000 * 4 MB
100 * 4 MB
100 * 4 MB
5000 * 400 KB
5000 * 400 KB
100 * 400 KB
DRCP
Connection
Broker
Overhead
Total Memory
© 2008 Oracle Corporation
5000 * 35 KB
22 GB
2.4 GB
610 MB
When to Use DRCP
• DRCP can be useful when any of the following apply:
• Large number of connections need to be supported with
minimum memory usage on database host
• Applications mostly use same database credentials for all
connections
• Applications acquire a database connection, work on it for a
relatively short duration, and then release it
• Multiple web server hosts
• Connections look identical in terms of session settings, for
example date format settings and PL/SQL package state
• Generally true for majority of web applications
© 2008 Oracle Corporation
Starting and Configuring DRCP
•
Start the pool:
SQL> execute dbms_connection_pool.start_pool();
•
Optionally Configure the Pool:
SQL> execute dbms_connection_pool.configure_pool(
pool_name =>
'SYS_DEFAULT_CONNECTION_POOL',
minsize
=> 4,
maxsize
=> 40,
incrsize
=> 2,
session_cached_cursors => 20,
inactivity_timeout => 300,
max_think_time => 600,
max_use_session
=> 500000,
max_lifetime_session => 86400);
© 2008 Oracle Corporation
DRCP: System Components
• Connection Broker
• New in Oracle Database 11g
• Oracle instance background daemon
• Handles initial authentication
• Handles subsequent connect/disconnect requests
• Pooled Servers
• New in Oracle Database 11g
• Oracle instance background slave processes
• Oracle 11g OCI Client library
• DRCP aware
© 2008 Oracle Corporation
DRCP: Connecting
© 2008 Oracle Corporation
DRCP: Doing Work
© 2008 Oracle Corporation
DRCP: After Disconnecting
© 2008 Oracle Corporation
Using DRCP with PHP
• No application code change required
• Unchanged PHP API
• Deployment decision to use DRCP
• Application can still talk to other Oracle versions
• Configure and start DRCP on Oracle Database 11g
dbms_connection_pool.configure_pool
dbms_connection_pool.start_pool
• Set php.ini parameters
oci8.connection_class = MYAPP
© 2008 Oracle Corporation
PHP OCI8 Best Practices
© 2008 Oracle Corporation
Example
$a = array(1, 2, 3, 4, 5); // data to insert
foreach ($a as $v) {
$s = oci_parse($c,
"insert into tab values ('".$v."')");
$r = oci_execute($s);
}
© 2008 Oracle Corporation
Bind Variables
Too Many Hard Parses
© 2008 Oracle Corporation
Lack of Bind Variables
• Hard Parse is expensive
• Creates shared cursor in SGA
• Causes library cache latch contention
• Causes shared pool contention
• Causes scalability issues
• Use Bind Variables
• Reduces hard parses on the server
• Reduces risk of SQL Injection: potential security issue
© 2008 Oracle Corporation
Use Bind Variables
$a = array(1, 2, 3, 4, 5);
// data to insert
$s = oci_parse($c, 'insert into tab values (:bv)');
oci_bind_by_name($s, ':bv', $v, 20);
foreach ($a as $v) {
$r = oci_execute($s);
}
© 2008 Oracle Corporation
Statement Caching: Minimize Soft
Parses
• PHP scripts issue the same statements repeatedly
• PHP OCI8 creates session specific OCI statement handle and
cursor context
• Results in soft parse: repeats metadata processing
• Use Statement Caching
• OCI8 extension has client side statement cache
• oci8.statement_cache_size = 20
• OCI Keeps frequently used session cursors open
• Reduces soft parses on the Server
• Cuts repeated metadata processing
• Consumes less network bandwidth
• Cuts code path in client/database tier
© 2008 Oracle Corporation
Auto Commits
• Beware. PHP OCI8 auto-commits by default
• Causes more transactions, log flushes
• Increases response time
• Breaks atomicity of the transactions
$a = array(1, 2, 3, 4, 5);
// data to insert
$s = oci_parse($c, 'insert into tab values (:bv)');
oci_bind_by_name($s, ':bv', $v, 20);
foreach ($a as $v) {
$r = oci_execute($s); // this is an auto-commit!
}
Auto-commits are inefficient
© 2008 Oracle Corporation
Turn off Auto-Commits
$a = array(1, 2, 3, 4, 5);
// data to insert
$s = oci_parse($c, 'insert into tab values (:bv)');
oci_bind_by_name($s, ':bv', $v, 20);
foreach ($a as $v) {
$r = oci_execute($s, OCI_NO_AUTO_COMMIT);
}
oci_commit($c);
This is better: Only one explicit commit
© 2008 Oracle Corporation
Stored Procedures
• Bundle multiple SQL statements in one call
• Use anonymous blocks or stored procedures
• Eliminates roundtrips to database
• Eliminates moving data between database and client
• Can improve performance dramatically
• Monitor roundtrips and bytes transferred stats
• High values may indicate optimization opportunities
© 2008 Oracle Corporation
Calling PL/SQL with OCI8
/* create or replace procedure
myproc(d_p in varchar2, i_p in number) as
begin
insert into mytab (mydata, myid) values (d_p, i_p);
end; */
<?php
$c = oci_connect('hr', 'hrpwd', '//localhost/XE');
$s = oci_parse($c, "call myproc('mydata', 123)");
oci_execute($s);
?>
© 2008 Oracle Corporation
Bulk Inserts (PHP Code)
$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);
© 2008 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;
© 2008 Oracle Corporation
Prefetching Reduces Roundtrips
Temporary buffer cache for query duration
$r = oci_fetch_array(...);
var_dump($r);
// array('1000', 'Roma')
$r = oci_fetch_array(...);
var_dump($r);
// array('1100', 'Venice')
No DB access
for next fetch
Reduces round trips
© 2008 Oracle Corporation
Prefetching is Enabled by Default
• Enabled by default oci8.default_prefetch = 100 rows
• Was 10 rows in OCI8 1.2
• Number of extra rows DB returns per fetch round-trip
• Value set doesn't alter oci_fetch_* behavior
• Reduces round trips
• Can tune per statement:
$s = oci_parse($c, 'select city from locations');
oci_set_prefetch($s, 87);
oci_execute($s);
while (($row = oci_fetch_array($s, OCI_ASSOC)) != false)
foreach ($row as $item)
print $item;
© 2008 Oracle Corporation
REF CURSOR Prefetching
• Works with Oracle 11.2 client libraries
• Even to older DBs
• Enabled by default
• Can set size per statement
© 2008 Oracle Corporation
REF CURSOR Prefetching
/* create or replace
procedure myproc(p1 out sys_refcursor) as
begin
open p1 for select * from tab;
end; */
$s = oci_parse($c, "begin myproc(:rc); end;");
$rc = oci_new_cursor($c);
oci_bind_by_name($s, ':rc', $rc, -1, OCI_B_CURSOR);
oci_execute($s);
oci_set_prefetch($rc, 200);
oci_execute($rc);
oci_fetch_all($rc, $res);
© 2008 Oracle Corporation
Client Result Cache
© 2008 Oracle Corporation
11g OCI Client Query Result Cache
like cache fusion between server and client
Application Server
Consistent
Caching
Database
• Caches SQL query results on client
• Targeted at repetitive queries against read-mostly, read-
only data
© 2008 Oracle Corporation
Benefits
• Easy to Use Cache
• With 11gR2
• Can be turned on without application/SQL changes
• CREATE TABLE foo (a NUMBER, b VARCHAR2(20)) RESULT_CACHE
(MODE FORCE);
• ALTER TABLE bar RESULT_CACHE (MODE FORCE);
• With 11gR1
• Add /*+ result_cache */ hint in SQL
• Frees application developers from building custom caches
• Extends server-side result caching to client side memory
• Leverages cheaper client-side memory
• Each application has its working set cached locally
• Achieves better performance by eliminating server roundtrips
• Improves server scalability by saving server resources
• Transparently maintains cache consistency with server side changes
© 2008 Oracle Corporation
Identifying Candidate Queries for
Client Result Caching from AWR
© 2008 Oracle Corporation
Identifying Candidate Queries for
Client Result Caching from AWR
© 2008 Oracle Corporation
Identifying Candidate Queries for
Client Result Caching from AWR
• Identify top SELECT statements
• BY CPU
• BY Elapsed Time
• Pick queries
• On tables that are not updated often
• With result sets can fit in available client memory
• Ideal candidates for client result caching
• Annotate base tables (using DDL) or add hints to
specific queries
• init.ora parameter
• CLIENT_RESULT_CACHE_SIZE
© 2008 Oracle Corporation
No DB Access When Client Cache Used
• Test shows reduced DB access when client caching
enabled:
SQL> select parse_calls, executions, sql_text
from v$sql where sql_text like '%CRCPARTS%';
PARSE_CALLS EXECUTIONS SQL_TEXT
----------- ---------- ----------------------------------2
100 select * from CRCPARTS
2
2 select /*+ result_cache */ * from CRCPARTS
© 2008 Oracle Corporation
Client Result Cache Load Test
© 2008 Oracle Corporation
End to End Tracing and
Monitoring
© 2008 Oracle Corporation
The Problem: Database Tracing in a
Typical PHP Application
• All web users run the same code:
$c = oci_connect('phpuser', 'welcome', 'localhost/orcl');
$s = oci_parse($c, 'select * from mytab');
oci_execute($s);
oci_fetch_all($s, $res);
• All database traces and logs show aggregated or non-
identifying results
• e.g. the Audit trail:
SQL> select username, extended_timestamp
from dba_audit_trail;
PHPUSER 07-SEP-10 06.18.31.658526 PM -07:00
...
© 2008 Oracle Corporation
Client Identifiers for Auditing,
Monitoring & VPD
• oci_set_client_identifier($c, 'Chris');
• i.e. name of end web-user, not the table owner
• Executed SQL in DB views, Enterprise Manager and
trace files are tagged with 'Chris'
• Client IDs identify the actual web user for:
• Auditing
• Monitoring
• Virtual Private Database
• Useful for web applications that
• always connects with the one DB username e.g. 'phpuser'
• implement their own authentication
© 2008 Oracle Corporation
Auditing with Client Identifiers
• Run application
<?php
session_start();
$enduser = $_SESSION['username']; // e.g. 'Chris'
$c = oci_connect('phpuser', 'welcome', 'localhost/orcl');
oci_set_client_identifier($c, $enduser);
$s = oci_parse($c, 'select * from mytab');
oci_execute($s);
oci_fetch_all($s, $res);
• View audit trail:
SQL> select client_id, username, extended_timestamp
from dba_audit_trail;
Chris PHPUSER 07-SEP-10 06.18.31.658526 PM -07:00
...
ꤠ
© 2008 Oracle Corporation
Monitoring: V$ Views or Enterprise
Manager
© 2008 Oracle Corporation
Metadata Values for Tracing &
Diagnostics
• Scripts can also set three levels of metadata
identifiers
• Used by DBAs to locate PHP code executing SQL
$c = oci_connect('phpuser', 'welcome', 'localhost/orcl');
oci_set_client_identifier($c, 'Chris');
oci_set_client_info($c, 'My Application Version 2');
oci_set_module_name($c, 'Home Page');
oci_set_action($c, 'Friend Lookup');
$s = oci_parse($c, 'select * from mytab');
oci_execute($s);
oci_fetch_all($s, $res);
© 2008 Oracle Corporation
High Availability
© 2008 Oracle Corporation
Fast Application Notification
• High Availability feature for PHP with RAC or Data
Guard with physical standby
• Usable with or without DRCP
• Available from Oracle 10gR2
• OCI8 supports FAN
© 2008 Oracle Corporation
FAN Configuration
• Tell DB to broadcast FAN Events
SQL> execute dbms_service.modify_service(service_name
=>'SALES', aq_ha_notifications =>TRUE);
• Configure PHP's php.ini so OCI8 listens for FAN
events
oci8.events = on
• Optionally add re-connection code to PHP application
© 2008 Oracle Corporation
Edition Based Redefinition in Oracle
11gR2
• EBR allows multiple versions of DB objects to be used
concurrently
• EBR allows application upgrade and testing while still
in production use
• PHP OCI8 1.4 has oci_set_client_edition()
© 2008 Oracle Corporation
In the News
© 2008 Oracle Corporation
In the News
• PHP OCI8 applications can connect to Oracle DB or
TimesTen
• New! PHP OCI8 with Oracle 11.2.0.2 libraries supports more
TimesTen features
• Tuxedo
• #1 Application Server for C, C++, COBOL, Python and Ruby
• New! PHP Support (previewed at OpenWorld)
• Tuxedo lets you scale up faster, with better resource
monitoring, and great support for legacy applications
© 2008 Oracle Corporation
Oracle Resources
•
Free Oracle Techology Network (OTN)
PHP Developer Center
otn.oracle.com/php
• Underground PHP and Oracle Manual
• Whitepapers, Articles, FAQs, links to blogs, Jdeveloper
PHP Extension, PHP RPMs
•
Excellent introduction to PHP with DRCP and FAN
• http://www.oracle.com/technetwork/topics/php/php-scalability-hatwp-128842.pdf
•
Information
[email protected]
blogs.oracle.com/opal
•
SQL and PL/SQL Questions
asktom.oracle.com
•
ISVs and hardware vendors
oraclepartnernetwork.oracle.com
© 2008 Oracle Corporation
Oracle Technology Network
PHP Developer Center
• Free
• Articles
• Install guides
• Underground PHP
and Oracle Manual
• Online forum
• PHP RPMs
• Oracle JDeveloper
10g PHP extension
otn.oracle.com/php
© 2008 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.
© 2008 Oracle Corporation