如何检查Application送往Oracle DB的Query
来源:互联网 发布:投屏软件 编辑:程序博客网 时间:2024/05/17 10:28
昨天,有一个Bug耗掉了我近一天的时间,写这篇学习笔记不是说那个Bug的,而是在解决的过程中,从shenglin那里(shenglin是COC的Senior Oracle DBA)学到了一些基本命令,命令都不复杂,不过我觉得对我挺有用的,至少以后我再碰到类似的问题,至少可以自己先试试而不是老要去麻烦DBA。
现象:
应用程序往数据库送了一跳insert语句。应用程序log文件中记录了这条SQL执行成功了:
insert into tableX(field1,field2,…fieldn) values(:val1,:val2,…:valn); tableX的主键是field1。我们知道val1 = XX。数据库那边没有报任何错误,可是select field1 from tableX where field1=XX 却返回空!
Trouble Shooting Steps:
1. 怀疑这条SQL是不是没有送到目标数据库
-bash-3.00$ hostname
arrowpig0.dev.ebay.com –>我的应用程序运行的机器名
然后我在另外一台dev机器上登录Oracle DB:
-bash-3.00$ sqlplus arrowpig/arrowpig@arrowpig –>关于登录Oracle数据库,参见安装Oracle 10g Express
SQL> set linesize 132 pagesize 10000
SQL> select sid,sql_hash_value,prev_hash_value,machine from v$session where machine like ‘%arrowpig0%’;
SQL> / -->当应用程序执行时,使用 / 反复执行查询语句
no rows selected
SQL> /
SID SQL_HASH_VALUE PREV_HASH_VALUE MACHINE
———- ————– ————— —————————————————————-
27 686872531 686872531 arrowpig0.dev.ebay.com
SQL> select sql_text from v$sqltext where hash_value=686872531 order by piece;
SQL_TEXT
—————————————————————-
insert into tableX (field1,field2,…fieldn) values(:val1,:val2,…:valn)
可以确定,SQL确实送到DB Server了。
2. 怀疑是不是没有Submit
SQL> select a.value ,b.name from v$sesstat a,v$statname b where a.STATISTIC#=b.STATISTIC# and b.name like ‘user commits’ and a.sid=27;
VALUE NAME
———- —————————————————————-
32 user commits
SQL> /
VALUE NAME
———- —————————————————————-
34 user commits
我们看到Value在增加,说明Commit成功了。
3. 怀疑是不是数据有错,手工输入SQL
于是我们想是不是有什么数据错。
在数据库端shenglin做了下面的操作(下面的操作需要sys权限):
drop trigger error_log_trigger ;
drop table sys.error_log ;
create table sys.error_log (
error_date date,
error_no number,
machine varchar2(64),
sqltext varchar2(4000)
) tablespace &tablespace_name;
create trigger error_log_trigger AFTER SERVERERROR ON DATABASE
declare
n number;
stmt varchar2(4000);
sql_text ora_name_list_t;
BEGIN
n := ora_sql_txt(sql_text); –ora_sql_text得到当前正在执行的DDL语句
FOR i IN 1..n LOOP –将sql_text的内容拼装成完成的一个字符串,存在stmt中
if(length(stmt||sql_text(i))> 4000) then
stmt := substr(stmt||sql_text(i), 1, 4000);
exit;
end if;
stmt := stmt || sql_text(i); — ||用于字符串连接
END LOOP;
insert into sys.error_log (error_date,error_no,machine,sqltext)
values (sysdate,server_error(1),sys_context(‘userenv’,'host’),stmt);
END;
/
SQL> select * from sys.error_log where machine like ‘%arrowpig0%’;
–记得做完实验以后把上面创建的表和触发器drop掉。
在应用程序端:
注意到我们送往DB的SQL都采用了绑定变量的方式,所以在现有的log中看不见具体的数据值。于是我在配置文件中加了一个选项DumpBindVariables,然后再修改一个源代码使得当DumpBindVariables=Enabled的时候打印所有绑定变量的值。
确定问题的Root Cause:
打印绑定变量以后,我们发现实际送往数据库的SQL中主键field1的值被绑定了数值YY,它应该是XX的。怪不得应用程序和数据库都没有报错,因为我们确实成功了插入了一条field1=YY的数据,但是我们select * from tableX where field1=XX当然就返回空了。我又花了不少时间,终于找到了出错的代码,这里我模拟一下大概的出错代码:
class record{
int32 meta_data;
int64 field1;
…
};
很不巧,给meta_data赋值的语句是这样的:
int32 tmp_meta_data=…;
memcpy(&record.meta_data, &tmp_meta_data,sizeof(int64));
完了,因为size错误,给meta_data赋值的时候覆盖了后面field1的前4个字节,导致field1的值被篡改。在茫茫代码中定位这样一个低级的错误很费时间。
我一直想知道有没有这样的断点,当程序试图修改某个pointer指向的内存时可以让程序停下来,并打印当前的调用堆栈,不知道GDB支持不支持这样的功能?
今天又碰到一个问题,发现我的SQL送到DB 以后Hold在那里:
SQL> select sid,sql_hash_value,lockwait,machine from v$session where machine like ‘%arrowpig0%’;SID SQL_HASH_VALUE LOCKWAIT MACHINE———- ————– —————- —————————————————————-5362 3075024559 0000000722B78180 arrowpig0.dev.ebay.com5487 834846608 arrowpig0.dev.ebay.com9154 0 arrowpig0.dev.ebay.com
想来想去想不通为什么会又把锁在那里,后来 DBA帮我看了一下,原因是处了应用程序,我还开了一个sqlplus,为了干净,我在启动应用程序之前执行了一把:SQL> delete from tableX;
但是我没有执行commit,所以这些被delete的记录都被加了锁。
检查加锁的SQL是:
SQL> select * from v$locked_object where object_id in ( select object_id from dba_objects where object_name=’xTable’);
- 如何检查Application送往Oracle DB的Query
- Oracle DB SQL Query 基础
- db.query的使用
- Oracle DB 运行状态检查
- Oracle db规范之 删除oracle 归档日志之前的几个检查项
- 如何检查oracle的高可用性属性
- 送往网吧的验尸报告
- 如何检查oracle死锁
- 如何使用C#在发送往client的内容上加js代码
- 如何使用C#在发送往client的内容上加js代码(转)
- 如何使用C#在发送往client的内容上加js代码
- 如何使用C#在发送往client的内容上加js代码(转)
- 如何使用C#在发送往client的内容上加js代码
- 如何使用C#在发送往client的内容上加js代码
- 如何使用C#在发送往client的内容上加js代码(转)
- oracle的db.properties
- discuz 如何添加数据DB::insert和更新数据DB::update 查询DB::query删除DB::delete
- discuz 如何添加数据DB::insert和更新数据DB::update 查询DB::query删除DB::delete
- C#打包应用程序(安装程序)
- 我的电信账单
- 关于在windows下部署发布QT程序的总结
- DLL(Dynamic Link Libraries)专题
- 找出索引键值出错的数据ID
- 如何检查Application送往Oracle DB的Query
- 网络编程
- windows共享不起作用的一个解决方法
- About Weblogic
- 敏捷开发
- 程序员的美:极致与疯狂
- 中国软件企业未来的黄金十年
- SQLite访问封装类
- 2010总结