在10G中,Fixed SGA Size+Redo Buffers不一定等于整数倍的Granule Size

为什么有这样的标题,是因为我们都知道这样的结论:
转载自eygle的文章《Granule 与 Redo Log Buffer (log_buffer) 的关系》:
http://www.eygle.com/archives/2009/07/granule_log_buffer.html


而实际上大家也发现,从Oracle10g开始,Redo Log Buffer缺省的已经是大大超过了原来的想象。
从Oracle 9i引入了Granule的概念后,在Oracle10g中,Oracle的内存分配会为'Fixed SGA Size'和'Redo Buffers'共享整数倍个Granule。



而且从metalink上我们也找到了同样说法的文章:
Oracle Calculation of Log_Buffer Size in 10g [ID 604351.1]
Modified 01-JUN-2010     Type HOWTO     Status PUBLISHED

The LOG_BUFFER size will be set by default, by Oracle internal algorithm.
In 10G R2, Oracle combines fixed SGA area and redo buffer [log buffer] together.
If there is a free space after Oracle puts the combined buffers into a granule, that space is added to the redo buffer. Thus you see redo buffer has more space than expected. This is an expected behavior.

Bug 4930608 documents this :
"In 10.2 the log buffer is rounded up to use the rest of the granule...
The granule size can be found from the hidden parameter "_ksmg_granule_size" "

In 10G the log_buffer could fall between the log_buffer specified in spfile and the granule size.
A minimum value can be specified, but Oracle can initialize it with a bigger value, as decided by its internal algorithm.

于是我也一直认为在10GR2中,有这样的公式存在:
(Fixed SGA Size)+(Redo Buffers)=N*(Granule Size). Where N is an integer.
我可以拿一个实例,来证明这个公式是成立的:
在pfile里,设置的log_buffer = 512000
SQL> select * from v$sgainfo where name in ('Fixed SGA Size','Redo Buffers','Granule Size');
NAME                                  BYTES RES
-------------------------------- ---------- ---
Fixed SGA Size                      2055512 No
Redo Buffers                       31498240 No
Granule Size                       33554432 No


这里

但是,事实并不是这样。至少,不全是这样。

经过检查多个库,这些库都是10GR2,得到下面信息:
其中Factor=(log_buffer(actually)+Fixed SGA Size)/Granule Size
DB(from haozhu)
Platform
Compatible
OS
memory
SGA
log_
buffers
(init.ora)
log_
buffers
(actually)
Fixed SGA Size
Granule
Size
Factor
1
T2000
10203
32G
22G
500K
30M
2M
32M
1
2
T5120
10203
64G
48G
500K
62M
2M
64M
1
3
T5120
10204
64G
56G
500K
62M
2M
64M
1  
4
T5240
10203
96G
77G
9M
9M
2M
32M
N/A
5
T5240
10203
96G
78G
500K
6M
2M
32M
1/4
6
T5240
9205
96G
86G
500K
2M
2M
64M
1/16
7
T5240
9205
96G
81G
500K
2M
2M
64M
1/16
8
T5120
9205
64G
49G
500K
62M
2M
64M
1


于是从上面在Sun SPARC平台各个T系机器上的表现来看,似乎,在T5240上,实际的log_buffers+Fixed SGA Size并不为整数倍的Granule Size。
我认为是因为当SGA的值超过了某个threshold后,log_buffers的自动计算就变得跟最上面的理论不一样了。

于是有如下实验性结论(因为没有任何文档佐证,所以仅供参考,真实性需要更多实例证明):

1.在10GR2,log_buffers+Fixed SGA Size会根据数据库的SGA计算出一个最小值,当log_buffer在init.ora里参数设定得比这个值小的时候,就会自动增加到这个最小值。
从以上例子来看,这也就是为什么,参数log_buffers是500K,但是会被自动增加。

2.在10GR2,当init.ora里log_buffers参数设定得比这个最小值大的话,就会使用参数log_buffers设定的值。也就是取两者取其大者。
从以上例子来看,从DB=4,由于我设定的log_buffers是9M,而这个最小值估计是6M(从DB=5推算出),而实际的log_buffers=9M。

3.在10GR2,当SGA比较小的时候:
(Fixed SGA Size)+(Redo Buffers)=N*(Granule Size). Where N is an integer.
从上面例子来看,DB=1,2,3,8都可以证明,此时N=1.

4.在10GR2,当SGA比较大的时候:
(Fixed SGA Size)+(Redo Buffers)=N*(Granule Size). Where N is NOT an integer.

其中,当compatible=10g时,N=1/4,当compatible=9i时,N=16/1。
从上面例子可以看出,DB=5时证明前半句,DB=6,7时证明后半句。

(BTW:1/4和1/16虽然出现在我的例子中,但我不保证随着SGA的不断增大,例如>100G以上,是否这个比例会更小,例如是否会出现1/64。)

这点似乎也是合理的或者说可以理解的,Oracle不希望当SGA很大时,自动地将log_buffers设得太大。

5.以上第3点和第4点对SGA的“小”和“大”的定义是有一个分界线的,即多小为“小”,多大为“大”。
这个threshold根据以上所有例子我可以估算在一个大小。

大约SGA达到70G以上时,可以认为其SGA“大”了,此时log_buffers+Fixed SGA Size就不满足整数个Granule Size了。
或许是1/4*Granule Size,或许是1/16*Granule Size...


希望大家能有其他大SGA情况下的log_buffers自动设定表现“异常”的例子,来推翻或者佐证这些实验结论。




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

转载于:http://blog.itpub.net/15415488/viewspace-667516/

### 实现C++自定义String类 为了创建一个具备基本功能的`String`类,可以考虑以下几个方面: #### 类成员变量 首先声明私有成员来存储字符数组以及字符串长度。 ```cpp class Mystring { private: char* str; size_t length; }; ``` 这允许内部管理动态分配的内存用于保存实际字符串数据[^1]。 #### 构造函数与析构函数 提供默认构造函数、带参数构造函数和拷贝构造函数,并实现析构函数以释放资源。 ```cpp public: // 默认构造函数 Mystring() : str(nullptr), length(0) {} // 带参构造函数 explicit Mystring(const char* s) { if (s != nullptr) { length = strlen(s); str = new char[length + 1]; strcpy(str, s); } else { str = nullptr; length = 0; } } // 拷贝构造函数 Mystring(const Mystring& source) { length = source.length; if (source.str != nullptr) { str = new char[source.length + 1]; strcpy(str, source.str); } else { str = nullptr; } } // 析构函数 ~Mystring() { delete[] str; } } ``` 上述代码展示了如何初始化对象并处理深浅复制问题。 #### 运算符重载 通过运算符重载使`Mystring`能够像内置类型一样操作。这里展示赋值运算符(`=`)的例子。 ```cpp // 赋值运算符 Mystring& operator=(const Mystring& rhs) { if (this == &rhs) return *this; delete[] str; length = rhs.length; if (rhs.str != nullptr) { str = new char[rhs.length + 1]; strcpy(str, rhs.str); } else { str = nullptr; } return *this; } ``` 此部分实现了安全的对象间赋值逻辑。 #### 成员方法 增加一些实用的方法如获取字符串大小、访问单个字符等。 ```cpp size_t get_length() const {return length;} char at(size_t pos) const {if(pos<length)return str[pos];else throw std::out_of_range("Out of range");} void append(const Mystring& other){ char* temp = new char[this->length + other.length + 1]; strcpy(temp, this->str); strcat(temp, other.str); delete[] this->str; this->str = temp; this->length += other.length; } ``` 这些辅助函数增强了类的功能性和易用性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值