
اگر دیتابیس Oracle کند شده، تعداد اتصالها افزایش پیدا کرده یا میخواهید بدانید چه کاربرانی به دیتابیس متصل هستند، اولین قدم بررسی Sessionهای فعال Oracle است.
با مشاهده Sessionها میتوانیم بفهمیم:
- چه کاربرانی به Oracle متصلاند؛
- هر کاربر از چه سیستم و برنامهای وصل شده است؛
- کدام Session فعال یا غیرفعال است؛
- هر Session چه دستور SQLای اجرا میکند؛
- کدام Session مدت زیادی مشغول اجراست؛
- چه Sessionهایی یکدیگر را قفل کردهاند؛
- چگونه یک Session مشکلساز را متوقف کنیم.
در این مقاله آموزش اوراکل از بخش CheatSheet، مهمترین و کاربردیترین کوئریهای مدیریت Session در Oracle را بهصورت خلاصه و عملی بررسی میکنیم.
اگر با Oracle Database کار میکنید، احتمالاً خیلی زود به این نتیجه میرسید که فقط بلد بودن چند دستور SELECT و JOIN کافی نیست.
در دنیای واقعی، چیزی که تفاوت ایجاد میکند این است که بتوانید کوئری درست، سریع، قابل نگهداری و بهینه بنویسید.
پیشنهاد می کنم این مقاله زیر رو حتما مطالعه کنی.
در این مقاله شما می خوانید
Session در Oracle چیست؟
هر زمان یک کاربر، برنامه یا سرویس به دیتابیس Oracle متصل میشود، یک Session ایجاد میشود.
برای مثال، اتصال از طریق ابزارها و سرویسهای زیر میتواند یک یا چند Session بسازد:
- Oracle SQL Developer
- SQL*Plus و SQLcl
- Oracle APEX و ORDS
- JDBC
- WebLogic
- نرمافزارهای سازمانی
- Connection Pool برنامهها
اطلاعات Sessionهای Oracle عمدتاً در View سیستمی زیر نگهداری میشود:
V$SESSION
در محیط Oracle RAC باید از نسخه سراسری این View استفاده کنیم:
GV$SESSION
مشاهده کاربران متصل به Oracle
برای مشاهده همه Sessionهای کاربری متصل به Instance فعلی، از کوئری زیر استفاده کنید:
SELECT
s.sid,
s.serial#,
s.username,
s.status,
s.osuser,
s.machine,
s.program,
s.module,
s.service_name,
s.logon_time
FROM v$session s
WHERE s.type = 'USER'
AND s.username IS NOT NULL
ORDER BY s.logon_time DESC;
معنی ستونهای مهم
| ستون | توضیح |
|---|---|
| SID | شناسه Session |
| SERIAL# | شماره تکمیلی برای شناسایی دقیق Session |
| USERNAME | نام کاربر Oracle |
| STATUS | وضعیت فعال یا غیرفعال Session |
| OSUSER | نام کاربر سیستمعامل مبدأ |
| MACHINE | نام سیستم یا سرور مبدأ |
| PROGRAM | برنامه ایجادکننده اتصال |
| MODULE | ماژول معرفیشده توسط برنامه |
| SERVICE_NAME | سرویس Oracle مورد استفاده |
| LOGON_TIME | زمان برقراری اتصال |
تفاوت Session فعال و غیرفعال در Oracle
وضعیت هر Session در ستون STATUS نمایش داده میشود. مهمترین مقادیر آن عبارتاند از:
ACTIVE: Session در حال اجرای یک Call است یا منتظر منبعی مانند Lock و I/O مانده است.INACTIVE: اتصال همچنان برقرار است، اما SQL فعالی اجرا نمیشود.KILLED: Session برای خاتمه علامتگذاری شده است.SNIPED: Session معمولاً به دلیل محدودیتهایی مانندIDLE_TIMEمنقضی شده است.
نکته مهم این است که ACTIVE بودن همیشه به معنای مصرف CPU نیست. ممکن است Session فعال باشد، اما منتظر قفل، دیسک، شبکه یا منبع دیگری مانده باشد.
مشاهده Sessionهای فعال Oracle
کوئری مشاهده Sessionهای فعال در Oracle
برای مشاهده Sessionهای فعال Oracle از کوئری زیر استفاده کنید:
SELECT
s.sid,
s.serial#,
s.username,
s.osuser,
s.machine,
s.program,
s.module,
s.service_name,
s.sql_id,
s.event,
s.wait_class,
s.state,
s.seconds_in_wait,
s.last_call_et AS call_elapsed_seconds,
s.logon_time
FROM v$session s
WHERE s.type = 'USER'
AND s.username IS NOT NULL
AND s.status = 'ACTIVE'
ORDER BY s.last_call_et DESC;
کوئری جامع مشاهده Sessionهای فعال Oracle
اگر بخواهیم اطلاعات اتصال، SQL جاری، وضعیت انتظار و Process سیستمعامل را در یک گزارش داشته باشیم، کوئری زیر انتخاب مناسبی است:
SELECT
s.sid,
s.serial#,
s.username,
s.status,
s.osuser,
s.machine,
s.program,
s.module,
s.action,
s.client_identifier,
s.service_name,
s.sql_id,
s.sql_child_number,
s.event,
s.wait_class,
s.state,
s.seconds_in_wait,
s.last_call_et AS call_elapsed_seconds,
s.logon_time,
p.spid AS server_os_pid,
q.sql_text
FROM v$session s
LEFT JOIN v$process p
ON p.addr = s.paddr
LEFT JOIN v$sql q
ON q.sql_id = s.sql_id
AND q.child_number = s.sql_child_number
WHERE s.type = 'USER'
AND s.username IS NOT NULL
AND s.status = 'ACTIVE'
AND s.audsid <> SYS_CONTEXT('USERENV', 'SESSIONID')
ORDER BY s.last_call_et DESC;
با این گزارش میتوانیم بفهمیم:
- چه کاربری به دیتابیس متصل است؛
- اتصال از کدام سیستم ایجاد شده است؛
- کاربر از چه برنامه یا ماژولی استفاده میکند؛
- کدام SQL در حال اجراست؛
- Call جاری چه مدت ادامه داشته است؛
- Session منتظر چه رویدادی است؛
- Process مربوط به آن در سیستمعامل سرور چیست.
مشاهده SQL در حال اجرای Sessionهای Oracle
برای مشاهده متن SQL جاری باید اطلاعات V$SESSION را به V$SQL متصل کنیم:
SELECT
s.sid,
s.serial#,
s.username,
s.status,
s.machine,
s.program,
s.module,
s.sql_id,
s.sql_child_number,
s.event,
s.wait_class,
s.last_call_et AS call_elapsed_seconds,
q.sql_text
FROM v$session s
LEFT JOIN v$sql q
ON q.sql_id = s.sql_id
AND q.child_number = s.sql_child_number
WHERE s.type = 'USER'
AND s.username IS NOT NULL
AND s.status = 'ACTIVE'
ORDER BY s.last_call_et DESC;
مشاهده متن کامل SQL در Oracle
ستون SQL_TEXT ممکن است فقط بخشی از دستور را نمایش دهد. برای دریافت متن کاملتر میتوانیم از SQL_FULLTEXT استفاده کنیم:
SELECT
s.sid,
s.serial#,
s.username,
s.machine,
s.program,
s.sql_id,
q.sql_fulltext
FROM v$session s
JOIN v$sql q
ON q.sql_id = s.sql_id
AND q.child_number = s.sql_child_number
WHERE s.type = 'USER'
AND s.username IS NOT NULL
AND s.status = 'ACTIVE';
پیدا کردن Sessionهای یک کاربر خاص
برای مشاهده Sessionهای کاربر HR از کوئری زیر استفاده کنید:
SELECT
s.sid,
s.serial#,
s.username,
s.status,
s.osuser,
s.machine,
s.program,
s.module,
s.sql_id,
s.logon_time,
s.last_call_et
FROM v$session s
WHERE s.type = 'USER'
AND s.username = 'HR'
ORDER BY s.logon_time DESC;
شناسایی اتصال بر اساس سیستم یا برنامه
جستوجو بر اساس سیستم مبدأ
SELECT
s.sid,
s.serial#,
s.username,
s.status,
s.machine,
s.osuser,
s.program,
s.module,
s.logon_time
FROM v$session s
WHERE s.type = 'USER'
AND s.username IS NOT NULL
AND UPPER(s.machine) LIKE UPPER('%APP-SERVER%')
ORDER BY s.logon_time DESC;
جستوجو بر اساس برنامه
SELECT
s.sid,
s.serial#,
s.username,
s.status,
s.machine,
s.program,
s.module
FROM v$session s
WHERE s.type = 'USER'
AND s.username IS NOT NULL
AND UPPER(s.program) LIKE '%SQL DEVELOPER%';
شناسایی Sessionهای APEX
SELECT
s.sid,
s.serial#,
s.username,
s.status,
s.machine,
s.program,
s.module,
s.action,
s.client_identifier,
s.service_name
FROM v$session s
WHERE s.type = 'USER'
AND s.username IS NOT NULL
AND (
UPPER(s.module) LIKE '%APEX%'
OR UPPER(s.program) LIKE '%ORDS%'
);
شمارش Sessionهای Oracle
تعداد کل Sessionهای متصل
SELECT COUNT(*) AS connected_sessions
FROM v$session
WHERE type = 'USER'
AND username IS NOT NULL;
تعداد Sessionهای فعال
SELECT COUNT(*) AS active_sessions
FROM v$session
WHERE type = 'USER'
AND username IS NOT NULL
AND status = 'ACTIVE';
تعداد Sessionها به تفکیک کاربر و وضعیت
SELECT
username,
status,
COUNT(*) AS session_count
FROM v$session
WHERE type = 'USER'
AND username IS NOT NULL
GROUP BY username, status
ORDER BY session_count DESC, username, status;
توجه داشته باشید که تعداد Sessionها با تعداد کاربران واقعی برابر نیست. یک کاربر دیتابیس میتواند چند اتصال همزمان داشته باشد، مخصوصاً در محیطهای دارای Connection Pool.
پیدا کردن Sessionهای طولانیمدت
برای مشاهده Sessionهایی که Call جاری آنها بیش از پنج دقیقه زمان برده است:
SELECT
s.sid,
s.serial#,
s.username,
s.machine,
s.program,
s.module,
s.sql_id,
s.event,
s.wait_class,
s.state,
s.last_call_et AS call_elapsed_seconds
FROM v$session s
WHERE s.type = 'USER'
AND s.username IS NOT NULL
AND s.status = 'ACTIVE'
AND s.last_call_et > ۳۰۰
ORDER BY s.last_call_et DESC;
مشاهده Sessionهای غیرفعال قدیمی
کوئری زیر Sessionهایی را نشان میدهد که بیشتر از یک ساعت غیرفعال بودهاند:
SELECT
s.sid,
s.serial#,
s.username,
s.status,
s.machine,
s.program,
s.module,
s.logon_time,
s.last_call_et AS inactive_seconds
FROM v$session s
WHERE s.type = 'USER'
AND s.username IS NOT NULL
AND s.status = 'INACTIVE'
AND s.last_call_et > ۳۶۰۰
ORDER BY s.last_call_et DESC;
مشاهده Transactionهای باز
پیش از بستن یک Session بهتر است بررسی کنیم که Transaction باز دارد یا خیر:
SELECT
s.sid,
s.serial#,
s.username,
s.status,
s.machine,
s.program,
s.sql_id,
t.start_time AS transaction_start_time,
t.used_ublk AS undo_blocks,
t.used_urec AS undo_records
FROM v$session s
JOIN v$transaction t
ON t.addr = s.taddr
WHERE s.type = 'USER'
AND s.username IS NOT NULL
ORDER BY t.start_time;
شناسایی Sessionهای قفلشده و قفلکننده
برای مشاهده Sessionهایی که منتظر Session دیگری هستند، میتوانیم از BLOCKING_SESSION استفاده کنیم:
SELECT
s.sid,
s.serial#,
s.username,
s.sql_id,
s.event,
s.wait_class,
s.seconds_in_wait,
s.blocking_session_status,
s.blocking_instance,
s.blocking_session
FROM v$session s
WHERE s.blocking_session IS NOT NULL
ORDER BY s.seconds_in_wait DESC;
برای نمایش مشخصات Session قفلشده و قفلکننده در محیط Single Instance:
SELECT
blocked.sid AS blocked_sid,
blocked.serial# AS blocked_serial,
blocked.username AS blocked_user,
blocked.sql_id AS blocked_sql_id,
blocked.event AS blocked_event,
blocked.seconds_in_wait,
blocker.sid AS blocker_sid,
blocker.serial# AS blocker_serial,
blocker.username AS blocker_user,
blocker.machine AS blocker_machine,
blocker.program AS blocker_program,
blocker.sql_id AS blocker_sql_id
FROM v$session blocked
JOIN v$session blocker
ON blocker.sid = blocked.blocking_session
WHERE blocked.blocking_session IS NOT NULL
ORDER BY blocked.seconds_in_wait DESC;
مشاهده Sessionهای فعال در Oracle RAC
برای مشاهده Sessionهای تمام Instanceها باید از GV$SESSION استفاده کنیم:
SELECT
s.inst_id,
s.sid,
s.serial#,
s.username,
s.status,
s.machine,
s.program,
s.module,
s.service_name,
s.sql_id,
s.event,
s.wait_class,
s.last_call_et AS call_elapsed_seconds,
s.logon_time
FROM gv$session s
WHERE s.type = 'USER'
AND s.username IS NOT NULL
AND s.status = 'ACTIVE'
ORDER BY s.last_call_et DESC;
در Oracle RAC، شناسایی کامل Session بر اساس ترکیب زیر انجام میشود:
INST_ID + SID + SERIAL#
مشاهده Sessionهای فعال در Oracle RAC به همراه SQL
SELECT
s.inst_id,
s.sid,
s.serial#,
s.username,
s.status,
s.osuser,
s.machine,
s.program,
s.module,
s.service_name,
s.sql_id,
s.event,
s.wait_class,
s.state,
s.last_call_et AS call_elapsed_seconds,
p.spid AS server_os_pid,
q.sql_text
FROM gv$session s
LEFT JOIN gv$process p
ON p.inst_id = s.inst_id
AND p.addr = s.paddr
LEFT JOIN gv$sql q
ON q.inst_id = s.inst_id
AND q.sql_id = s.sql_id
AND q.child_number = s.sql_child_number
WHERE s.type = 'USER'
AND s.username IS NOT NULL
AND s.status = 'ACTIVE'
ORDER BY s.last_call_et DESC;
نحوه بستن Session در Oracle
بعد از شناسایی دقیق Session میتوانیم آن را با دستور زیر خاتمه دهیم:
ALTER SYSTEM KILL SESSION 'SID,SERIAL#' IMMEDIATE;
مثال:
ALTER SYSTEM KILL SESSION '123,45678' IMMEDIATE;
تولید خودکار دستور Kill Session
کوئری زیر دستور Kill را برای Sessionهای کاربر HR تولید میکند:
SELECT
s.sid,
s.serial#,
s.username,
s.status,
'ALTER SYSTEM KILL SESSION '''
|| s.sid
|| ','
|| s.serial#
|| ''' IMMEDIATE;' AS kill_command
FROM v$session s
WHERE s.type = 'USER'
AND s.username = 'HR';
بستن Session در Oracle RAC
در محیط RAC باید INST_ID را نیز مشخص کنیم:
ALTER SYSTEM KILL SESSION 'SID,SERIAL#,@INST_ID' IMMEDIATE;
مثال:
ALTER SYSTEM KILL SESSION '123,45678,@2' IMMEDIATE;
دسترسیهای لازم برای مشاهده Sessionهای Oracle
اگر کاربر اجازه مشاهده Dynamic Performance Viewها را نداشته باشد، ممکن است با خطای زیر مواجه شود:
ORA-00942: table or view does not exist
DBA میتواند حداقل دسترسیهای لازم را اعطا کند:
GRANT SELECT ON v_$session TO report_user;
GRANT SELECT ON v_$process TO report_user;
GRANT SELECT ON v_$sql TO report_user;
GRANT SELECT ON v_$transaction TO report_user;
برای بستن Session نیز مجوز زیر لازم است:
GRANT ALTER SYSTEM TO admin_user;
سوالات متداول درباره مشاهده Sessionهای فعال در Oracle
SELECT
sid,
serial#,
username,
status,
machine,
program,
logon_time
FROM v$session
WHERE type = ‘USER’
AND username IS NOT NULL
ORDER BY logon_time DESC;
شرط زیر را به کوئری اضافه کنید:
AND status = ‘ACTIVE’
خیر. یک Session فعال ممکن است روی CPU باشد یا منتظر Lock، I/O، شبکه و منابع دیگر بماند. برای تحلیل دقیق باید EVENT، WAIT_CLASS، STATE و SQL_ID را نیز بررسی کنید.
خیر. Sessionهای INACTIVE در Connection Poolها معمولاً طبیعی هستند. قبل از Kill باید برنامه مبدأ، مدت غیرفعالبودن و وجود Transaction باز بررسی شود.
SID شناسه Session است و SERIAL# کمک میکند Session فعلی از Session قبلی با همان SID تشخیص داده شود.
برای Kill کردن یک Session به هر دو مقدار نیاز داریم.
جمعبندی
برای مشاهده سریع کاربران متصل به Oracle این کوئری کافی است:
SELECT
s.sid,
s.serial#,
s.username,
s.machine,
s.program,
s.module,
s.sql_id,
s.event,
s.wait_class,
s.state,
s.last_call_et AS call_elapsed_seconds,
q.sql_text
FROM v$session s
LEFT JOIN v$sql q
ON q.sql_id = s.sql_id
AND q.child_number = s.sql_child_number
WHERE s.type = 'USER'
AND s.username IS NOT NULL
AND s.status = 'ACTIVE'
AND s.audsid <> SYS_CONTEXT('USERENV', 'SESSIONID')
ORDER BY s.last_call_et DESC;
سؤالی درباره این مقاله داری؟
اگر نکتهای در این مقاله برات مبهم بود یا خواستی بیشتر بدونی، همین حالا برام بنویس تا دقیق و صمیمی پاسخت رو بدم — مثل یه گفتوگوی واقعی 💬
برو به صفحه پرسش و پاسخ
دیدگاهتان را بنویسید