oracledba.help
SpecialTopics

Shared Server

Overview

Shared Server is described as a method to allow more connections to a database than is possible in dedicated mode. It comes with a lot of negative side affects. Just say no to Shared Server! If you want constant unexplained errors, terrible performance and potential data corruption then Shared Server is for you! You should suspect any DBAs credentials if they are proponent of Shared Server for a production server. With Shared Server routine negative database phenomena are guaranteed.

In most cases the best ROI is to change the application connection handling code and not implement Shared Server. Some methods that are effective include:

  • Use application connection pooling.
  • Create a single connection object and have all your SQL calls use this one (1) connection.
  • Ensure connections are closed and as quickly after opening as possible.

There is no reason to open, and keep open, excessive Oracle database connections in this day and age.

Connections Sidebar

Modern Oracle databases can handle thousands of simultaneous cursors. Thousands!!! So the question is really: why is the application trying to run SQL over so many connections when just a few will do fine? The answer = Legacy Programming Practices folks.

I commonly use this parameter: OPEN_CURSORS=2500

Are you still reading this (sorry to hear that)? What follows are the changes required to enable Shared Server for an instance called DB01. This should allow 350-600 connections in most environments. Test it for yourself then change the settings as required after allowing your Shared Server to be active for at least a day (better a week).

It might be a good investment to bounce both the database and listener weekly if you use Shared Server.

Config Files

SPFILE Entries

This is really where all the changes are to enable Shared Server. The other files are included just for reference.

dispatchers          (ADDRESS=(PROTOCOL=TCP)(HOST=192.168.1.42))(DISPATCHERS=5)
local_listener       LISTENER_DB01
max_shared_servers   50
open_cursors         2000
pga_aggregate_target 1073741824
processes            500
sessions             1200
sga_max_size         1572864000
sga_target           1073741824
shared_servers       30

listener.ora

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = DB01)
      (ORACLE_HOME = C:\oracle\product\10.2.0\db_1)
      (GLOBAL_DBNAME = DB01)
    )
  )

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.42)(PORT = 1521))
    )
  )

sqlnet.ora

SQLNET.AUTHENTICATION_SERVICES = (NTS)

Display

Status

-- ss_status.sql
-- spool C:\oracle\scripts\spool\shared_server_info.spool

SET pagesize 9999

COL "%TIME BUSY" FORMAT 99.9999
COL circuit      FORMAT a10
COL network      FORMAT a50
COL busy         FORMAT 999999
COL name         FORMAT a10
COL paddr        FORMAT 999999999
COL requests     FORMAT 999,999,999
COL status       FORMAT a15

clear screen

PROMPT [Shared Server Monitor]
SELECT MAXIMUM_CONNECTIONS "MAX CONN", MAXIMUM_SESSIONS "MAX SESS",
   SERVERS_STARTED "STARTED", SERVERS_TERMINATED "TERMINATED",
   SERVERS_HIGHWATER "HIGHWATER"
FROM V$SHARED_SERVER_MONITOR;
PROMPT

PROMPT [Performance]
SELECT NAME "NAME", PADDR, REQUESTS,
  (BUSY/(BUSY + IDLE)) * 100 "%TIME BUSY", STATUS
FROM V$SHARED_SERVER;
PROMPT

PROMPT [Dispatcher Rate]
SELECT * FROM V$DISPATCHER_RATE;
PROMPT

PROMPT [Circuit]
SELECT SADDR, CIRCUIT, DISPATCHER, SERVER, SUBSTR(QUEUE,1,8) "QUEUE",WAITER FROM V$CIRCUIT;
PROMPT

PROMPT [Shared Server]
SELECT NAME,PADDR,STATUS,MESSAGES,BYTES,BREAKS,CIRCUIT,IDLE,BUSY,REQUESTS
FROM V$SHARED_SERVER;
PROMPT

PROMPT [Dispatchers]
SELECT NAME "NAME", SUBSTR(NETWORK,1,23) "PROTOCOL", OWNED,
STATUS "STATUS", (BUSY/(BUSY + IDLE)) * 100 "%TIME BUSY"
FROM V$DISPATCHER;
PROMPT

PROMPT [Queue]
SELECT * FROM V$QUEUE;
PROMPT

PROMPT [Connection Info]
SELECT SERVER, SUBSTR(USERNAME,1,15) "USERNAME",
    SUBSTR(OSUSER,1,8) "OS USER", SUBSTR(MACHINE,1,7) "MACHINE",
    SUBSTR(PROGRAM,1,35) "PROGRAM"
    FROM V$SESSION
    WHERE TYPE='USER';
-- spool off

Connections

-- ss_conns.sql
clear columns
col username format a10 justify center heading "Username"
col sid format 9999 justify center heading "Session ID"
col server format a10 justify center heading "Connection"
col spid format 99999 justify center heading "OS ID"
col status format a10 justify center heading "Status"
col type format a15 justify center heading "Session Type"

select se.username, se.sid, se.server, p.spid, se.status, se.type
from v$session se, v$process p
where p.addr = se.paddr
and se.username is not null
order by se.username desc, se.sid
/

Dispatchers

-- ss_dispatchers.sql
-- If percent busy is too high add more. Whats to high well ask yourself is it slow?
clear columns
col p format a5 justify center heading "Protocol"
col name format a5 justify center heading "Dispatcher"
col cc format 9999 justify center heading "Current|Connections"
col status format a9 justify center heading "Status"
col accept format a6 justify center heading "Accept"
col b format 990.99999 justify center heading "% Busy"

compute sum of cc on p
compute avg of b on p
break on p skip 1

select substr(upper(d.network),instr(upper(d.network),'PROTOCOL=')+9,3) p, d.name,
d.status, d.accept,count(c.dispatcher) cc, (busy/(busy+idle))*100 b
from v$dispatcher d, v$circuit c
where d.paddr = c.dispatcher(+)
group by substr(upper(d.network),instr(upper(d.network),'PROTOCOL=')+9,3), d.name,
d.status, d.accept, (busy/(busy+idle))
order by 1, 2
/

Performance

-- ss_SrvPerf.sql
-- Look for the Percent busy, if its too high add shared servers.
-- Maximum performance means you have a single shared server with 0 requests.

clear columns
col name format a5 justify center heading "Server"
col status format a12 justify center heading "Status"
col requests format 9,999,999
justify center heading "Requests"
col idle/100 format 9,999,999.00 justify center heading "Idle (sec)"
col busy/100 format 9,999,999.00 justify center heading "Busy (sec)"
col b format 999.999 justify center heading "% Busy"

compute avg of b on report
break on report

select name, status, requests, idle/100, busy/100, (busy/(busy+idle))*100 b
from v$shared_server
order by 1
/

<- SpecialTopics