2009年2月26日星期四
The key points for memory configuration
1. 系统管理员需要决定ASE可以使用的内存总量,并设置'max memory'值;
2. 在系统启动时和系统运行时都可以通过设置'allocate max shared memory'值将ASE使用的内存动态收集到'max memory'大小;在某些系统上过大的shared memory segments会对系统表现造成不利影响,需要了解系统平台相关文档以决定'max memory'大小;
3. 配置其他影响内存分配的配置参数;
4. 'max memory'和'total logic memory'之间的差值可以用于procedure cache和data cache或者其他配置参数。
5. 当处理大字符串的数据查询时,ASE并不是静态的将数据缓冲分配到最大值,而是进行动态的分配。当有需要时,它将把buffer扩充到最大值,而不论其是否需要。这会造成处理大字符串查询时ASE系统性能有一个边际损失;
6. 一个表数据行超过1000列或者1个存储过程参数超过10000个,那么ASE需要为内部数据结构分配更多的内存。一些小任务的增加将会造成ASE性能表现的下降;
7. 动态的分配内存将会对ASE系统有轻微影响;
8. 当使用较大的logic page size时,每次ASE从硬盘获取与logic page size同样大小的数据块,这样会增加I/O吞吐量。
2009年2月25日星期三
Sybase ASE12.5内存配置(2)
1. logic page size
所有的数据库及数据库中的对象都采用同样的logic page size,logic page size在安装ASE时指定,可选项有2,4,8和16K。allocation page,object allocation map(OAM) page,data page,index page,text page等都建立在logic page之上。更大的logic page size值可以使你能创建更大的row,同时也可以使数据库读取数据时的效率更高,因为每一页更大,所包含的数据也更多。
logic page size是一个服务设定值,你无法对单个数据库进行单独设置,同时数据库中的每一行也不能存在于多个页之上。
extent: 数据库为对象分配空间时使用extent,每一个extent相当于8个logic page size大小。
更大的logic page size值也使得一些小的表的空间的最后一页所剩余的空间也更大。
数据库根据logic page size 不同,需要的最小磁盘空间数也不同,见下表:
2K 2MB
4K 4MB
8K 8MB
16K 16MB
内存分配的配置参数与logic page size不尽相同,无论logic page size设置多大,绝大多数内存分配参数采用2K,其中包括一下几个重要的内存配置参数:
2. 磁盘空间分配
磁盘空间分配以2K为单位。
3. logic page size不是默认时的处理
当logic page size设置为2K时,default data cache默认是8M大小,等于2048 buffers,而logic page size是16k时,如果仍然采用8M的default data cache,则只有256 buffers。如果buffer数量过小,在一个忙碌的系统中,buffers总是处于重写过程中,会导致系统整个运行速度变慢。所以当logic page size是默认的4倍时,你也需要将default data cache也设为默认的4倍。
4. Heap memory
Heap memory是在启动时即已确定,用于当用户任务所耗堆内存过大时动态分配heap memory给用户任务使用,用户任务完成后将归还给heap memory。这样,可以减少预先设定给用户任务(user connections, worker processes)的堆内存,同时提高效率。
配置参数是heap memory per user, sp_configure 'heap memory per user',***(amount_of_memory),单位是byte,默认是4096bytes。
sp_configure 'heap memory per user', 10 给10个用户连接分配默认heap memory。
sp_configure 'heap memory per user', 0, "4K" 给每个用户分配4k的heap memory。
ASE初始化分配给heap memory总量是1M,不包括在刚才指定分配的内存中。初始的heap memory将会用于所有的user connections和worker processes。所以,以下两个参数与heap memory的分配密切相关:
number of user connections
number of worker processes
查看现有heap memory size使用命令:select @@heapmemsize
4.1. 计算ASE设置的heap memory size
((1024 * 1024) + (heap memory in bytes)* (number of user connections + number of worker processes) )
For example, if your server is configured for:
* heap memory per user : 4K
* number of user connectins : 25 (the default)
* number of worker processes : 25 (the default)
@@heapmemsize reports 1378304 bytes.
And the estimated value using the formula above, is:
((1024 X 1024) + (4 * 1024 * 50)) = 1253376
Now, if you increase the number of user connections, the size of the heap memory pool increases accordingly:
sp_configure 'user connections', 100
@@heapmemsize reports 1716224 bytes.
The estimated value in this case comes out to be:
((1024 * 1024) + (4 * 1024 * (100 + 25) ) = 1560576
5.
Sybase ASE内存分配(1)
修改$servername$.cfg
[Named Cache:default data cache]
cache size = DEFAULT
cache status = default data cache
cache replacement policy = DEFAULT
local cache partition number = DEFAULT
修改cache size = DEFAULT
然后重新配置
没有修改ASE启动时的默认配置文件$servername$.cfg,而是将修改之前的ASE配置文件备份(如$servername$.033之类)修改名称替换掉当前不正确的cfg配置文件,重新启动后ASE恢复正常。
思考ASE启动失败的原因,在Sybase的《系统管理员教程》中,《14. 配置内存》中讲到如果ASE不能得到配置的内存,就可能无法启动。
那么如何正确的分配内存呢?
1. 确定计算机总的物流内存;
2. 从总的物流内存中减去操作系统和其他必备服务、软件所占用的内存;
3. 减去backup server 、Monitor Server和其他与ASE Server相关软件所耗用的内存;
4. 如果计算机非ASE专用,减去其他系统所需内存;比如X-window等客户应用程序;
5. 减去分配给additional network memory配置参数的任何内存;
剩下的内存即是ASE可用的总内存,可参考此值设置total memory的值。
我认为一个比较简便的方法是不启动ASE,而将Backup Server和Monitor Server以及其他必备服务、程序启动起来,观察计算机所剩内存,由此确定Total Memory。
当遇到以下情况时应该考虑修改total memory值:
1. 计算机RAM数量改变时;
2. 当计算机使用模式改变时;(不太明白?)
3. 如果为ASE的 addtional network memory分配了内存。
下图是Sybase ASE内存分配示意图。
其中,过程高速缓存和数据高速缓存根据procedure cache percent进行分配。
在12.5版本中,sybase内存分配有所区别,请见图
2009年2月24日星期二
如何修改Syabse服务器端的默认字符集
来源: 赛迪网 日期:2008-11-07 我要评论
在安装完Sybase后,很多人在使用isql或程序插入中文数据后发现,查询出的数据是乱码(中文字符全为?),这是因为客户端的字符集和服务端的字符集不一致造成的,Sybase默认安装后默认字符集为:iso_1。通常使用中文字符集在Sybase内是cp936。那么如何设置Sybase的字符
在安装完Sybase后,很多人在使用isql或程序插入中文数据后发现,查询出的数据是乱码(中文字符全为‘?’),这是因为客户端的字符集和服务端的字符集不一致造成的,Sybase默认安装后默认字符集为:iso_1。通常使用中文字符集在Sybase内是cp936。那么如何设置Sybase的字符集呢?修改方法如下:
以Windows操作系统Sybase15为例:
首先说明察看服务端字符集和客户端字符集的方法:
查看服务器端字符集:
在isql环境中执行:
1>; sp_helpsort
2>; go
查看客户端字符集:
在isql环境中执行:
1>; select @@client_csname
2>; go
修改服务端字符集方法:
假设sybase安装目录为$sybase$
◆1.转到$sybase$\ASE-15_0\bin目录
执行命令:charset -Usa -P binary.srt cp936
◆2.打开isql,执行下面的SQL查询出cp936对应的id
select id , name from syscharsets where name = 'cp936'
go
假设查询结果为171
执行下面语句设定默认字符集
sp_configure 'default char',171 --可能有误,以上面的查询结果为准
go
关闭ASE
shutdown
go
◆3.重新启动sybase服务两次(第一次启动会失败),启动服务。
如何扩展master数据库空间
如何扩展master数据库空间
master数据库只能扩展在master设备上.那么当master设备已经没有足够的空间可使用时,请按以下步骤操作:
(此操作过程是以UNIX操作系统为例.SYBASE安装路径为/sybase)
1.备份master数据库
启动backup server,进入isql环境执行:
1>dump database master to '/sybase/master.dump'
2>go
hut down SQL/ASE Server
1>shutdown
2>go
*shutdown时如果服务处于忙碌状态,可以使用shutdown with nowait命令直接关掉sybase sqlserver服务无须等待。
2.创建新的足够大的master设备
$buildmaster -d
例:$buildmaster-d /sybase/data/master.dat –s102400
*buildmaster是老版本的执行程序,在ASE12.5及其以上版本是ASE-12_5/bin/sqlsrvr.exe。
3.修改RUN_servername文件
编辑RUN_server_name文件,-d参数指向新建的设备名。
4.单用户模式重启server
$startserver -f RUN_servername –m
*这是采用单用户模式启动服务。startsrv.exe在ASE-12_5\install\中。
5.执行installmaster脚本
*执行方法可以采用isql –Usa –P*** –S*** -iinstallmaster的方法。
6.由备份文件装载master数据库
1>load database master from '/sybase/master.dump'
2>go
7.修改sysdevices信息
sp_configure 'allow updates', 1
go
begin tran
go
update sysdevices set high = 102399 , phyname = 'e:\sybase\data\master_test.dat' where name = 'master'
go
(102399=200*512-1 master设备大小为200M)
commit tran
go
*采用isql登陆后执行。在修改时可能会出现master数据库日志已满的情况,这时只要执行dump transaction master with truncate_only截断日志即可执行余下步骤。
8.扩展master数据库
1>alter database master on master设备名称=size(此值以M为单位)
2>go
例:alter database master on master=10
将master数据库在master设备上扩展10M
*执行成功后,重启服务,并备份master设备。
2009年2月23日星期一
firefox插件
Adblock Plus
AutoSlideshow
Browse Images
CoolPreviews
Delicious Bookmarks
DownThemAll!
Flashblock
Google Gears
Firebug
Google Toolbar
Google Preview
Greasemonkey
IE Tab
Image Zoom
Interclue
Linkification
MediaWrap
Save Images
SearchWith
Tab Mix Plus
TabRenamizer
Web Developer
2009年2月20日星期五
2009年2月17日星期二
一个关于Java线程waite()、notifyAll()的例子
- /////
- // ProducerConsumer.java
- //
- // 这是个很重要的Thread例子。需要注意的是:
- // wait() 必须在synchronized 函数或者代码块里面
- // wait()会让已经获得synchronized 函数或者代码块控制权的Thread暂时休息,并且丧失控制权
- // 这个时候,由于该线程丧失控制权并且进入等待,其他线程就能取得控制权,并且在适当情况下调用notifyAll()来唤醒wait()的线程。
- // 需要注意的是,被唤醒的线程由于已经丧失了控制权,所以需要等待唤醒它的线程结束操作,从而才能重新获得控制权。
- //
- // 所以wait()的确是马上让当前线程丧失控制权,其他的线程可以乘虚而入。
- //
- // 所以wait()的使用,必须存在2个以上线程,而且必须在不同的条件下唤醒wait()中的线程。
- //
- //
- // 以下的例子:
- // ProductStack 是一个生产者跟消费者共享的同步机制,这个机制决定了什么情况生产者要wait(),什么情况消费者要wait()
- // 可以把ProductStack看作一个产品仓库。当产品仓库满的时候,生产者线程需要wait(),从而放弃对产品仓库的控制。
- // 这个时候消费者线程就可以进来了而取得仓库的控制权。一旦消费者消费了产品,那么仓库就不满了。
- // 这个时候消费者线程就要notifyAll()生产者线程,让等待的生产者线程唤醒。
- // 但是生产者被唤醒后不能马上进行生产,因为它在wait()的时候已经丧失了对仓库的控制权,所以就需要等待消费者线程结束操作,
- // 才能重新取得仓库的控制权,再进行生产。
- //
- // 所以特别注意的是,notifyAll()并不是让当前线程马上让出控制权,而只是让其他wait()当中的线程唤醒而已,
- // 所以对不起,尽管我唤醒你,可你必须还是要等我用完仓库才能进来。这点必须清楚。
- //
- // 相反,仓库如果空的时候,消费者线程就会wait(),然后等待生产者线程来生产产品,生产者进程乘虚而入后,让生产者线程生产产品
- // 并且唤醒消费者线程。这个情况跟上面就类似了。
- //
- ///
- public class ProducerConsumer {
- public static void main(String[] args) {
- ProductStack ps = new ProductStack();
- Producer p = new Producer(ps, "生产者1");
- Consumer c = new Consumer(ps, "消费者1");
- new Thread(p).start();
- new Thread(c).start();
- }
- }
- class Product {
- int id;
- private String producedBy = "N/A";
- private String consumedBy = "N/A";
- // 构造函数,指明产品ID以及生产者名字。
- Product(int id, String producedBy) {
- this.id = id;
- this.producedBy = producedBy;
- }
- // 消费,需要指明消费者名字
- public void consume(String consumedBy) {
- this.consumedBy = consumedBy;
- }
- public String toString() {
- return "Product : " + id + ", produced by " + producedBy
- + ", consumed by " + consumedBy;
- }
- public String getProducedBy() {
- return producedBy;
- }
- public void setProducedBy(String producedBy) {
- this.producedBy = producedBy;
- }
- public String getConsumedBy() {
- return consumedBy;
- }
- public void setConsumedBy(String consumedBy) {
- this.consumedBy = consumedBy;
- }
- }
- // 这个class就是仓库,是生产者跟消费者共同争夺控制权的同步资源
- class ProductStack {
- int index = 0;
- Product[] arrProduct = new Product[6];
- // push使用来让生产者放置产品的
- public synchronized void push(Product product) {
- // 如果仓库满了
- while (index == arrProduct.length) // 这里本来可以用if(),但是如果catch
- // exception会出问题,让满的index越界
- {
- try {
- // here, "this" means the thread that is using "push"
- // so in this case it's a producer thread instance.
- // the BIG difference between sleep() and wait() is, once
- // wait(),
- // the thread won't have the lock anymore
- // so when a producer wait() here, it will lost the lock of
- // "push()"
- // While sleep() is still keeping this lock
- // Important: wait() and notify() should be in "synchronized"
- // block
- System.out.println(product.getProducedBy() + " is waiting.");
- // 等待,并且从这里退出push()
- wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.println(product.getProducedBy() + " sent a notifyAll().");
- // 因为我们不确定有没有线程在wait(),所以我们既然生产了产品,就唤醒有可能等待的消费者,让他们醒来,准备消费
- notifyAll();
- // 注意,notifyAll()以后,并没有退出,而是继续执行直到完成。
- arrProduct[index] = product;
- index++;
- System.out.println(product.getProducedBy() + " 生产了: " + product);
- }
- // pop用来让消费者取出产品的
- public synchronized Product pop(String consumerName) {
- // 如果仓库空了
- while (index == 0) {
- try {
- // here will be the consumer thread instance will be waiting ,
- // because empty
- System.out.println(consumerName + " is waiting.");
- // 等待,并且从这里退出pop()
- wait();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.out.println(consumerName + " sent a notifyAll().");
- // 因为我们不确定有没有线程在wait(),所以我们既然消费了产品,就唤醒有可能等待的生产者,让他们醒来,准备生产
- notifyAll();
- // 注意,notifyAll()以后,并没有退出,而是继续执行直到完成。
- // 取出产品
- index--;
- Product product = arrProduct[index];
- product.consume(consumerName);
- System.out.println(product.getConsumedBy() + " 消费了: " + product);
- return product;
- }
- }
- class Producer implements Runnable {
- String name;
- ProductStack ps = null;
- Producer(ProductStack ps, String name) {
- this.ps = ps;
- this.name = name;
- }
- public void run() {
- for (int i = 0; i < 20; i++) {
- Product product = new Product(i, name);
- ps.push(product);
- try {
- Thread.sleep((int) (Math.random() * 200));
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- class Consumer implements Runnable {
- String name;
- ProductStack ps = null;
- Consumer(ProductStack ps, String name) {
- this.ps = ps;
- this.name = name;
- }
- public void run() {
- for (int i = 0; i < 20; i++) {
- Product product = ps.pop(name);
- try {
- Thread.sleep((int) (Math.random() * 1000));
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }