本篇文章給大家帶來了關于oracle的相關知識,其中主要介紹了查看鎖及session執行中的sql的相關問題,下面一起來看一下,希望對大家有幫助。
推薦教程:《oracle》
本文測試數據的數據庫環境:oracle 11g
? ? ? ? ? ?為什么說是session執行中的sql呢,某個session的sql執行記錄好像獲取不到,也看了很多的博文,網上很多有說通過視圖v$active_session_history和v$sqlarea關聯sql_id就能查詢到某個session的sql執行記錄,經過實踐發現是不行的(通過表dba_hist_active_sess_history試過了也是不行),某些sql的sql_id在v$active_session_history根本就沒有記錄,我嘗試修改參數:control_management_pack_access,發現我沒有權限,而且我對了一下,參數值是正常的,該參數數據庫是開啟的,參考博文:Oracle V$ACTIVE_SESSION_HISTORY查詢沒有數據 – wazz_s – 博客園
? ? ? ? 通過v$sqlarea視圖能查詢到sql的執行記錄,但卻查不到執行該sql的sessionid,如果有這個sessionid該多好,我就能查到那個人執行了該sql。
? ? ? ? 如果我要查詢導致鎖表的那一條sql,網上大部分的博文都是這樣教的,通過查詢視圖v$session得到對應的prev_sql_addr字段值,記為值A,然后通過值A作為視圖v$sqlarea字段address的查詢條件值,然后就可以查詢到對應的sql記錄了。這種作為練習測試你是可以找到找到鎖表的sql,但是在正常生產環境下大部分情況下你是獲取不到的,為什么呢,請看下文的介紹。
本文以探索的方式進行學習,為了保證數據的準確性,我開了三個數據庫會話,分別記為session1、session2、session3,具體步驟如下:
1? 在會話session1中新建測試表及測試數據
--新建測試表 create table zxy_table(zxy_id int,zxy_name varchar2(20)); --插入數據 insert into zxy_table(zxy_id,zxy_name) values(1,'zxy1'); insert into zxy_table(zxy_id,zxy_name) values(2,'zxy2'); insert into zxy_table(zxy_id,zxy_name) values(3,'zxy3'); insert into zxy_table(zxy_id,zxy_name) values(4,'zxy4'); commit;
2? 查看session1的會話Id
select userenv('sid') from dual;
可以看到會話Id為2546
3? 在session1中,通過select? for update的對表zxy_table的某一行進行鎖定,如下:
select * from zxy_table where zxy_name='zxy1' for update;
4? 在session2中,查詢到該會話id為2189:
然后在session2中對表zxy_table值為zxy_name=’zxy1’的行進行update,如下:
update zxy_table set zxy_name='zxy1_modify' where zxy_name='zxy1';
然后看到該sql已經被堵塞了,如下圖:
5? 然后我們來到會話session3查看鎖表的情況了
首先查看表v$locked_object?
select * from v$locked_object;
?可以看到造成鎖表的會話id為2546,就是前面的session1,同時object_id為110154,當然咯,在生成環境中,你看到的肯定不止一條記錄,你要多執行幾遍,執行n遍后,還能看到的記錄,證明這條記錄就是鎖表的記錄
通過object_id:110154查詢dba4_objects表查詢詳細鎖表的信息
select object_name as 被鎖的表名稱,obj.* from dba_objects obj where object_id='110154';
?通過sessionid:2546查詢視圖v$session
select s.prev_sql_addr, module as 客戶端工具名稱, s.user# as 數據庫賬號名, s.osuser as 連接數據庫客戶端對應的window賬號名稱, s.machine as 連接數據庫客戶端對應的計算機名稱, s.* from v$session s where sid='2546';
?得到prev_sql_addr的值為:000000012E045E28,然后通過得到的值查詢視圖v$sqlarea
select * from v$sqlarea where address='000000012E045E28';
?從上圖中可以看到造成鎖表的語句了,但是很多博文到了這一步就完事了,這樣查詢真的靠譜嗎?答案是不靠譜的,你可以回到session1中隨便執行一條sql ,如下:
select * from zxy_table;
然后你再到session3執行
select s.prev_sql_addr, module as 客戶端工具名稱, s.user# as 數據庫賬號名, s.osuser as 連接數據庫客戶端對應的window賬號名稱, s.machine as 連接數據庫客戶端對應的計算機名稱, s.* from v$session s where sid='2546';
?再看看prev_sql_addr是不是變了,從000000012E045E28變為了00000001FB03CEC0,再通過00000001FB03CEC0查詢視圖v$sqlarea
select * from v$sqlarea where address='00000001FB03CEC0';
得到的sql_text是select * from zxy_table,你敢說這條sql導致了鎖表嗎?所有只能說是session1當前執行的sql,而且你很難保證session1執行完鎖表的sql:?select * from zxy_table where zxy_name=’zxy1′ for update且在提交前不再執行別的sql,這就是前文提出的問題的答案。
推薦教程:《oracle》