Sybase数据库产品自从1987年问世以来,它的客户机/服务器(client/server)工作模式、分布处理的基础体系结构、完善的安全保密性能、高速快捷的运行方式、多平台跨操作系统的广泛应用等优点,迅速被IT界接受并推广应用。我们作为金融业的用户,也在1995年开始使用Sybase10版本。在具体的使用中,发现集中式的数据管理有其优点,就是数据风险范围大为缩小,但是作为Sybase的服务器一端,数据风险比较集中,如何做好数据库的数据备份,成为至关重要的问题。 

 

在实际应用中,我们总结出了两种全量备份方案: 

一、使用Sybase的Backup Server(备份服务器),做Dump备份

转储数据库(Dump database),就是为整个数据库(包括数据、表结构、触发器、游标、存储过程、事务日志等)做一次物理备份。转储数据库时,系统自动执行一次checkpoint,即将日志和数据从缓冲区拷贝到硬盘(只拷贝脏页),把已被分配的页(日志和数据)转储到设备。 

命令格式为:dump database 数据库名 to 设备文件名 with 参数

如果备份到硬盘的文件上,可以不预先估算备份文件的大小,只要硬盘有足够的存储空间就可以。如果是备份到dds磁带上,那么就要估算一下备份后的大小,90米的dds磁带压缩存储空间为4G,120米的磁带压缩存储空间为8G,如果数据库的备份文件超过了这个尺寸,就要考虑多文件转储,使用stripe参数。 

命令格式为:dump database 数据库名 to 设备文件名1 stripe on 设备文件名2 stripe on 设备文件名3…… with 参数

这种数据备份方式是将整个数据库的运行环境完整的复制一份,包括数据库的脏页和碎片,在使用load命令恢复时,只能恢复到同样大小的数据库中(数据和日志的大小都只能和原来完全一致),适用于在每天的日终营业网点下班后的日常备份。优点是数据库完整无误,缺点是不能直接查看备份内容。 

 

二、分数据结构和数据记录做两次备份

在一般情况下,生产机的数据库都比较庞大,而实验机则相对较小,难以在实验环境中以load命令恢复工作机的内容。所以,在工作实践中,我们摸索出了第二种全量备份方案。 

 

1、数据结构备份 

在windows平台的Sybase SQL Server Manager(数据库管理)平台中选择ServeràGenerate ddl则产生整个数据库服务器的所有信息,如果选择databaseàgenerate ddl则产生所选定数据库的信息,以master库为例,产生的文件主要包括:config.ddl(配置)、devices.ddl(设备)、database.ddl(数据库)、logins.ddl(用户)、remote.ddl(远程)、cache.ddl(缓冲)、segment.ddl()、group.ddl(用户组)、user.ddl(用户)、default.ddl(确省)、rule.ddl(规则)、udt.ddl、table.ddl(表)、view.ddl(视图)、proc.ddl(存储过程)、triger.ddl(触发器)。 

 

2、数据记录备份 

将数据库各表以Sybase自代的bcp(bulk copy)工具的方式导成一定格式的文本文件。

命令格式: bcp 表名 out 路径名 文件名 -c -t 分隔符 -u (用户名)-p(密码)-S(服务器名)

如果将一个数据库中的所有表都做一个bcp备份,就需要针对每一个表都做一次bcp,在一般情况下,一个数据库有100多个表,工作量比较大。可以利用数据库中的系统表信息做一个bcp备份脚本。原理是每一个用户表在系统表中都有信息记载,可以通过isql语句查询得到。

现举一例说明: 

1)先编辑一个名为mkbcpout.sql的文件,

内容如下: 

1> select "echo bcp '"+name+" out ……………………' "+"bcp "+name+" out ./"+name+".table -c -t '|' -Uuser -Ppassword -SSERVER" from sysobjects where type='U' 

2> go

2)执行isql命令,以此文件作为输入,执行结果输出到另外一个文件里: 

$ isql -Uuser -Ppassword -S server -I mkbcpout.sql -O bcpout

3)对bcppout文件稍微修改,增加可执行权限:

$ chmod +x bcpout

4)执行bcpout,导出数据文本 

$ ./bcpout

 

3、数据库恢复 

业务生产机可能为小型机,而实验开发环境的硬件环境为PC server,安装好win nt或SCO unix下的Sybase服务器后,根据需要创建空间足够大的数据库和tempdb(系统临时数据库),创建数据库用户,并将其更改为此数据库的所有者。

要注意两点:

1)此数据库允许bcp拷贝。

2)此数据库自动清除log。

命令格式为: 

1> sp_dboption databasedbname ,"select into/bulkcopy",true 

2> go 

1> sp_dboption databasename,"trunc log on chkpt",true 

2> go

 

上述两个配置可能与生产机的配置不同。 

 

然后以新创建的数据库用户登录,导入数据结构,注意要首先导入表结构,然后才是存储过程、触发器等等。

命令格式: 

1、$isql -Uusername -Ppassword -I table.ddl -o error.log.table

2、$isql -Uusername -Ppassword -I proc.ddl -o error.log.proc 

……

为了提高bcp导入数据的速度,需要将比较大的表的索引和主键删除,否则的话,每bcp进一条数据,数据库都自动写一条log日志,记载此数据的上一条和下一条记录,确定本记录在此表中的准确位置,一是影响bcp速度,二是数据库的log飞速膨胀。数据库的自动清除log功能只有在一个事务结束后才起作用。 

准备工作做完后,开始倒入数据记录。使用类似做bcpout的方法做一个bcpin的脚本,然后执行:

$./bcpin |tee error.bcpin

 使用tee管道输出的目的是让计算机完整记录下倒入过程,自动存入error.bcpin文件中,待倒入结束后,我们只需要检查日志文件,不需要一直紧盯着计算机屏幕。 

所有工作做完之后,不要忘记重新将删除的主键和索引建上。 

如果有现成的数据库,只需要单纯地导入数据记录,则首先将数据库中所有用户表(也就是所有type="U"的表)清空,

命令格式: 

1> truncate table tablename

2> go

当然最好也是利用做bcpout脚本的做一个truncate脚本,通过执行此脚本将所有用户表清空。然后的数据导入、处理索引和主键的过程与上面类似。 

 

三、利用做bcp备份脚本的方法做数据库碎片整理

Sybase数据库作为联机事务处理应用服务器,每天应用程序都对数据库做大量的插入、修改和删除等操作,不可避免的在数据库的物理存储介质上留下页碎片和扩展单元碎片,从而影响数据库的存储效率和运行速度。具体表现为:业务繁忙时出现死锁(dead lock),数据库的输入/输出资源被大量占用,业务处理速度慢。

其解决办法是: 

1、 清空数据库中的所有表。

命令格式: 

$ isql -Uusername -Ppassword -I truncate.sql -o error.truncate 

2、 删除所有表的索引和主键。 

$ isql -Uusername -Ppassword -I dropindex.sql -o error.dropindex

3、 导入数据 

$ ./bcpin

4、 添加索引和主键 

$ isql -Uusername -Ppassword -I addindex.sql -o error.addindex

5、 更新数据库状态 

1> update statistics tablename

2> go

上述操作都是针对数据库中的所有用户表进行的,利用做bcp备份脚本的方法做出相应的脚本,使繁琐的数据库维护变得简便易行,还克服了直接使用isql语句操作风险大、没有操作日志的毛病。 

笔者在实际工作中,使用第一种方法对生产机做日常全量备份,日终通过unix的crontab定时批量作业(具体做法请参考《中国金融电脑》2001年第10期有关crontab的文章)bcp出全部数据。使用高档PC server 搭建模拟运行环境,在需要的情况下导入生产机数据,处理运行中后台server的各种问题,待研究出解决办法后再在生产机上做相应调整,这样做风险小,效果好。

 

****************************************** 启动脚本 ***********************************************

 

#!/bin/sh

 PrgPID=`ps -ef|grep -w dataserver|grep -v grep|awk '{print $2}'`
 if [ "x$PrgPID" != "x"  ]; then
         echo "sybase server running"
         exit
 else
         echo "starting sybase server "
         startserver -f /sybase/ASE-15_0/install/RUN_CmoasXz 
 fi

  PrgPID=`ps -ef|grep -w backupserver|grep -v grep|awk '{print $2}'`
 if [ "x$PrgPID" != "x"  ]; then
         echo "sybase backup server is running"
         exit
 else
         echo "starting sybase backup server"
         startserver -f /sybase/ASE-15_0/install/RUN_SYB_BACKUP
 fi

 

**************************************************************************************************** 

需要在备份前启动sybase的备份服务,启动方式如下:

 

以下是代码片段:

startserver -f RUN_SYBASE //启动SYBASE服务 

RUN_SYBASE: 
#!/bin/sh 

# Master device path: /home/sybase/data/master 
# Error log path: /home/sybase/install/SYBASE.log 
# Directory for shared memory files: /home/sybase 
# Adaptive Server name: SYBASE 

/home/sybase/bin/dataserver \ 
-d/home/sybase/data/master \ 
-e/home/sybase/install/SYBASE.log \ 
-M/home/sybase \ 
-sSYBASE \ 

startserver -f RUN_SYBASE_BAK //启动sybase备份服务 

RUN_SYBASE_BAK: 
#!/bin/sh 

# Error log path: /home/sybase/install/SYB_BACKUP.log 
# Maximum number of network connections: 25 
# Maximum number of server connections: 20 
# Backup Server name: SYB_BACKUP 

/home/sybase/bin/backupserver \ 
-e/home/sybase/install/SYB_BACKUP.log \ 
-N25 \ 
-C20 \ 
-SSYB_BACKUP \ 

 

*********************************************** 数据库关闭 ******************************************

 isql -U数据库名 -P登陆口令 

 

1> shutdown SYB_BACKUP
2> go
Backup Server: 3.48.1.1: The Backup Server will go down immediately.
Terminating sessions.
1> shutdown
2> go  *

******************************************************************************************************

 

通过defncopy实现快速导出表结构

 在需要对一些存储过程单独进行备份时,往往使用defncopy通过拼串的方式进行。具体步骤如下:

1.根据需要备份的存储过程,先编写此crtprocout.sql文件,假设导出所有以PR_JF开头的存储过程,内容如下:

select "defncopy -U用户名 -P口令 -S联机串名 out "+name+".sql 库名 "+name from sysobjects where type='P' and name like "PR_JF%"

 2.利用上述文件,生成导过程脚本

isql -U用户名 -P口令 -S联机串名 –I crtprocout.sql –o procout

 3.改变文件procout的权限

chmod +x procout

 4.执行脚本导出过程,每个过程脚本名为:过程名+后缀”.sql”

./procout

小结:以上两种办法通过修改sql语句里的where条件相互之间是可以代替的。但笔者认为,前者适合对整库的过程进行备份,而后者适合对指定的几个过程进行备份。因为前者会对所有的过程脚本生成到一个文件里,适合面向多个过程的管理和备份;而后者一个过程脚本生成一个文件,适合面向单个过程的管理和备份。以上两种方法通过简单修改也可进行触发器等的导出。