ORACLE动态性能视图统计值溢出

今天同事在查询V$SQL视图的时候发现BUFFER_GET列出现了负值。研究了一下,感觉应该是Oracle的整型数溢出了。


查询Oracle的V$SQL视图,发现其中一条SQL:SELECT 1 FROM DUAL的BUFFER_GETS变成了负值:

SQL> select to_char(buffer_gets) from v$sql where sql_text = 'SELECT 1 FROM DUAL';

TO_CHAR(BUFFER_GETS)
----------------------------------------
-2069050280

1 row selected.

为什么会出现负数呢,除了bug外似乎没有别的解释,不过即使是bug,Oracle也没有道理写一个负数到动态视图中的。

观察一下执行次数:

SQL> select executions, to_char(buffer_gets) from v$sql where sql_text = 'SELECT 1 FROM DUAL';

EXECUTIONS TO_CHAR(BUFFER_GETS)
---------- ----------------------------------------
742004326 -2068982372

对于DUAL表的扫描,一般每次执行都是3个逻辑读。

SQL> select 742004326*3 from dual;

742004326*3
-----------
2226012978

数量级是一样的,只不过buffer_gets的值是负的。

一般来说出现负值都是由于存储数值的变量发生溢出造成的。Oracle的number类型是38位,存储最大数值可以达到10的125次方,不可能在这么小的数值发生溢出。

不过Oracle的核心程序是用C语言写的,C的int型变量是32位的:

SQL> select to_char(power(2, 32)) from dual;

TO_CHAR(PO
----------
4294967296

这个上限值是对于unsigned int而言的,对于可以表示正书和负数的int类型而言,上限仅仅是这个值的一半。

SQL> select 742004326 * 3 - power(2, 32) / 2 from dual;

742004326*3-POWER(2,32)/2
-------------------------
78529330

显然是由于BUFFER_GETS的值已经超出了这个上限值。而且C采用的补码的算法,当超过最大值2147483647后,数值开始从-2147483648向-1递增。

观察上面两次对BUFFER_GETS的查询,该值已经从-2069050280增加到了-2068982372。

Oracle在这里应该使用UNSIGNED INT类型或者LONG类型来保存数值,就不会出现这个问题了。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/4227/viewspace-69394/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/4227/viewspace-69394/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值