Sybase从Windows到Linux的迁移指南(使用资源文件来快速新建sybase服务器)

已在solaris10,ASE12.5.2下用资源文件resource_files新建了一个4k的sybase服务器。测试该方法通过!
不过在windows下没有这个命令srvbuildres,相类似的命令工具为sybatch,况且windows下还要配置注册表信息才能启动服务除非你想每次都通过RUN_servername来启动!

本指南实际为本人两篇文章的合集,分为安装和迁移两大部分

第一部分:在无GUI环境下安装sybase for linux 12.5.0.1

通常我们建立sybase for linux数据库服务器的时候,都是执行asecfg来建立数据
库,但是这种方式是需要在
服务器上安装X的,即使是通过X FORWARD的方式来操作,也至少需要安装上X
lib。在许多时候下,我们都希望
在服务器上安装的软件包越精越好,即只需要在console环境下就能建立好我们所
需要的服务器。
sybase for linux 就提供了这样一套无需任何X软件包的数据库建立工具---
srvbuildres,它通过读取资源文件
来完成基于console的数据库建立工作。

一 安装rpm包
rpm -ivh --nodeps <rpm包名>

二 激活sybase帐号
passwd sybase

三 设置内核参数
echo $( expr <你的内存容量(以MB为单位)> \* 1024 \* 1024 ) >
/proc/sys/kernel/shmmax
echo "kernel.shmmax = "$( expr <你的内存容量(以MB为单位)> \* 1024 \*
1024 ) >> /etc/sysctl.conf
echo "本机ip hostname" >> /etc/hosts

四 创建数据库服务器和备份服务器
以sybase帐号登录
cp ~/ASE/init/sample_resource_files/srvbuild.adaptive_server.rs ~/server.rs
cp ~/ASE/init/sample_resource_files/srvbuild.backup_server.rs ~/backup.rs
编辑 server.rs

sybinit.release_directory: USE_DEFAULT
sybinit.product: sqlsrv
sqlsrv.server_name: kbibm_ase <--- 填入你所准备起的数据库服务器名称, 这里是我的数据库服务器名字
sqlsrv.new_config: yes
sqlsrv.do_add_server: yes
sqlsrv.network_protocol_list: TCP
sqlsrv.network_hostname_list: <--- 填入数据库服务器所在主机的主机名
sqlsrv.network_port_list: <---端口号
sqlsrv.server_page_size: USE_DEFAULT
sqlsrv.force_buildmaster: no
sqlsrv.master_device_physical_name: /opt/sybase-12.5/data/master.dat
<--- 设定master文件所在位置
sqlsrv.master_device_size: 100 <--- size以MB为单位,这里建立100MB大小的
设备文件。
sqlsrv.master_database_size: 90 〈--- master_database 的size 至少要小于
master_device 7MB,所以这里填90MB
sqlsrv.errorlog: USE_DEFAULT
sqlsrv.do_upgrade: no
sqlsrv.sybsystemprocs_device_physical_name:
/opt/sybase-12.5/data/systemprocs.dat
sqlsrv.sybsystemprocs_device_size: 200 <--- 建立200MB大小的systemprocs设
备文件
sqlsrv.sybsystemprocs_database_size: 200
sqlsrv.sybsystemdb_device_physical_name:
/opt/sybase-12.5/data/sybsystemdb.dat
sqlsrv.sybsystemdb_device_size: 200 <--- 建立200MB大小的sybsystempdb设备文件
sqlsrv.sybsystemdb_database_size: 200
sqlsrv.default_backup_server: kbibm_bak <--- 填入你所准备建立的备份数据库名

备份服务器的rs文件也按此方式进行修改

五 执行srvbuildres来建立数据库
$SYBASE/ASE/bin/srvbuildres -s $SYBASE -r <rs文件>

六 建立sqlloc.rs来设置本地化
sybinit.release_directory: USE_DEFAULT
sqlsrv.server_name: kbibm_ase
sqlsrv.sa_login: sa
sqlsrv.sa_password: serverj
sqlsrv.default_language: us_english
sqlsrv.language_install_list: us_english
sqlsrv.language_remove_list: USE_DEFAULT
sqlsrv.default_characterset: cp850
sqlsrv.characterset_install_list: cp850
sqlsrv.characterset_remove_list: USE_DEFAULT
sqlsrv.sort_order: binary

执行$SYBASE/ASE/bin/sqlloc sqlloc.rs 设置locale

七 由于/etc/init.d/sybase中有两处存在bug,所以我们要修改它
将SYBASE_ASE=`basename $SYBASE/ASE*` 改为 SYBASE_ASE=`basename $SYBASE/ASE`
将SYBASE_OCS=`basename $SYBASE/OCS*` 改为 SYBASE_OCS=`basename $SYBASE/OCS`
否则将不能正常启动sybase

八 /etc/init.d/sybase restart

现在我们就可以用 isql -U sa -P -S <数据库服务器名> 登录进去了。

以上步骤在redhat 7.3 上操作通过。

------------------------------------------------------------------------------

第二部分:将Sybase for Windows 12.5的数据库迁移到Sybase for Linux 12.5平台。

软件环境
-------------------
源数据库:Adaptive Server Enterprise/12.5/SWR 9616 GA/P
目的数据库:Adaptive Server Enterprise/12.5.0.1/EBF 10292 IR

操作系统:Redhat 7.3

硬件环境
----------
IBM Netfinity 5600

遇到的问题:
当把Sybase for Windows上dump下来的数据库备份文件load 到Sybase for
Linux上后,客户端程序连线运行后报出错信息"You must drop
and re-create xxxx",应用程序无法正常运行。

问题的分析:
   经分析sybase提供的出错信息,发现当把Sybase数据库从Windows向Linux跨平台迁
移时要求重建数据库的存储过程和缺省值,而且只能是删除后重建,sp_recompile
命令不起作用。如果只是小型的业务系统,手工删除、重建存储过程和缺省值并不
是很困难的事,而对于大型的数据库系统可能存有上百条存储过程和缺省值,手工
重建是不现实的。
   Sybase并没有提供一套供管理员使用的批量重建存储过程和缺省值的管理工具。
为此,我自行编写了sql命令文件来实现自动化重建缺省值和存储过程的功能。

   缺省值的重建比存储过程的重新建要简单一些。附件是重建缺省值的sql文件
通过isql -Usa -S<服务器名> -i sybwintolinux.sql,将该sql文件导入sybase
for linux数据库中,该sql将在
sybsystemprocs库中建立一个名为sp_rebuild_defaults的存储过程来重建指定数
据库中的所有缺省值。
使用方法为 sp_rebuild_defaults <目标数据库名>

存储过程的重建则要复杂一些,我是采了以下步骤操作:
一.首先我们先要把原有的存储过程代码导出到外部文件中
  1. use <业务数据库名>
     go
     select a.text into tempdb..procs from syscomments a, sysobjets b
where b.type = 'P' and b.id = a.id
     go
  2. $ bcp tempdb..procs out procs.sql -Usa -S<服务器名> -r '' -c
  3. $ sed -e 's/endcreate/end\ngo\ncreate/g' procs.sql > newprocs.sql
       在newprocs.sql文件原有内容之前增加 use <业务数据库名> 两行
                                          go
       在原有内容最后,增加 一条 go命令
  现在,我就获得了一份完整的业务数据库中的存储过程源代码文件。

二.删除业务数据库原有的存储过程
  1.$ sed -n -e 's/create\ proc[a-z]*\ /drop\ procedure\ /g w dropprocs.sql' newprocs.sql
       在dropprocs.sql文件内容之前增加 use <业务数据库名> 两行
                                       go
       在最后新增一行, 写入 go命令
    现在就得到了一个用于删除原有存储过程的sql文件
  2. $ isql -Usa -S<服务器名> -i dropprocs.sql
     删除业务系统中原来的存储过程,注意,在操作前,最好再仔细检查一遍
dropprocs.sql文件。

三.导入存储过程到数据库中
   $ isql -Usa -S<服务器名> -i newprocs.sql
     将存储过程重新导入Sybase数据库中,Sybase将会自动重新编译所有的存储
过程。

完成以上操作后,将客户端程序重新连上Sybase for linux,经测试运行正常。

总结:
1.将Sybase从Windows平台向Linux平台的迁移会遇到需要重新编译数据库对象的问
题,这里列举的是存储过程和缺省值,由于我这里没有建立过触发器和规则,所以
还不清楚是否也要重建。
2.对于大型业务数据库只有采用命令脚本的方式进行自动重建,但需要DBA仔细检
查sql脚本,特别注意一定要先备份出存储过程的源代码后再删除原存储过程。
3.在某一论坛的贴子有人说从Sybase for Linux 12.5.3开始,Sybase能自动重建跨平台数据库备份文件中的所有数据库对象(存储过程,缺省值,触发器,规则等),但未经证实。

最新情况,经询问Sybase技术专家,得知自Sybase 12.5.2开始,ASE具备了自动重建跨平台数据库
对象的功能了。也就不需要再按以上方式重建对象了,但我在解决上述问题时采取的一些思路
和积累的经验仍对本人在以后的工作中处理类似的问题提供了参考。

  • 本文链接地址:http://www.sybrepair.com/ase-migrate-from-windows-to-linux.htm
  • 本文为dbainfo个人原创,请在尊重作者劳动成果的前提下进行转载;
  • 转载务必注明原始出处 : Sybase数据库技术,数据库恢复专家
  • 对《Sybase从Windows到Linux的迁移指南(使用资源文件来快速新建sybase服务器)》有何疑问或见解,请在本文下方发表;
  • 对网站还有其他问题或建议,请提交在留言板,谢谢!
    1. Eisen
      2010-12-17 14:36:07

      windows上一样可以通过resource file来创建instance,其类似srvbuildres的命令叫做sybatch.exe,其%SYBASE%\%ASE%\init里面的那个sample sqlsrv.res文件就是。
      另:通过dump,load跨平台的时候,由于要求dump时数据库必须处于静默状态,所以往往都是先从production给dump一份出来,然后load到同平台的另一个无人用的db上去,再dump出来才能跨平台,之后还得dbcc reindex()…还真挺麻烦,我看还不如用ddl的方式建架子,然后脚本走proxy_table转数据的好。

    2. dbainfo
      2010-12-17 14:53:58

      由于要求dump时数据库必须处于静默状态,是因为sybase在ASE15.x中不支持跨平台dump&load transaction。

      用ddl的方式建架子,让我觉得麻烦的是对象间的依赖关系不能“全部”导出,或者先后顺序不对。只能第一遍报错的时候再执行第二遍。如果在ASE15中利用了自定义函数。sybase central 和ddlgen是导不出来函数语法的,除非在sybase central中人工一个一个的复制函数定义。 另外PowerDesigner反工程能得到函数定义语法。

      关于这个问题: 我感觉扩平台备份恢复不是一个经常性的工作,建议用系统自带的dump&load。如果此活是经常性的工作的话,那用你说的ddl+data的方法比较好,因为毕竟熟悉了嘛。

    3. Eisen
      2010-12-18 10:38:54

      也是,所以我后来自己开发了那个小工具专门来导出procedure和function的脚本的。
      而且用ddl+data的方法因为可以完全写成脚本自动运行—— 1. 导table 2.导proxy_table 3.导两次view 4. 导function 导两次procedure 5.导data 6. 导trigger 7.导索引和key,这样就可以自己跑去睡觉去了不是吗?呵呵

      • dbainfo
        2010-12-19 16:22:40

        两种方法:跨平台dump&load 和 ddl+data,个人感觉ddl+data更能够锻炼DBA或者开发人员的能力。
        从你说的上述步骤中:1. 导table 2.导proxy_table 3.导两次view 4. 导function 导两次procedure 5.导data 6. 导trigger 7.导索引和key,
        这些是个基本的能力,拿到其他数据库,比如oracle,mysql都是通用的。而跨平台dump&load 不是,甚至它还有很多的限制。

        你导出的table,view,function,proxy_table,procedure,index&键 是通过ddlgen实现的呢?还是利用自己写的工具完全自己根据系统表来提取的?
        我知道至少函数function的语法需要自己写工具导出。

    4. Eisen
      2010-12-18 10:40:33

      另外再补充一下,个人感觉对象之间的依赖关系在迁移中没啥重要的,所以只要脚本前面有drop statement的就没有问题了。你觉得呢?

      • dbainfo
        2010-12-19 16:14:49

        drop statements对于更新对象的DDL是很有用的。

        在移植对象DDL的时候,举个例子:表A外键引用表B,如果导出的DLL语句中表A的定义语句在前面,而表B的DDL在后面。那么在创建表A的时候会因为外键引用的表B不存在而导致表A创建不成功。表B是能够成功创建的。

        第二次执行上面相同的脚本时,首先会成功创建表A,因为其所引用的表B已经创建上了。而表B不会再次创建因为上次执行的时候已建上,会给出一个错误信息。这在isql是个错误信息,可能在sybase central中会是一个让人讨厌的弹出窗口。

        总之,如果数据库内表之间定义了引用关系,那么同样的脚本语句需要执行两边才能成功完成工作。下面举一个外键引用的例子,分两种情况:1:不带if exitsts …. drop table …
        2:带if exitsts …. drop table …
        有两种表:部门信息表dept,学生信息表students,学生表中的部门编号列引用表dept的dept_id列。语法如下:
        use tempdb
        go
        create table students ( id int not null,name varchar(30) null,
        dept_id int not null,constraint fk_students_dept_id foreign key(dept_id) references dept(dept_id) )
        go
        create table dept(dept_id int unique not null, dept_name varchar(100) null)
        go

        第一种情况:不带if exitsts …. drop table …
        执行第一遍语句
        1> create table students ( id int not null,name varchar(30) null,
        2> dept_id int not null,constraint fk_students_dept_id foreign key(dept_id) references dept(dept_id) )
        3> go
        Msg 1710, Level 16, State 3:
        Server ‘NMR’, Line 1:
        Referenced table ‘dept’ specified in a referential constraint declared on
        ‘students’ does not exist in the database ‘tempdb’.
        Msg 2761, Level 16, State 4:
        Server ‘NMR’, Line 1:
        Failed to create declarative constraints on table ‘students’ in database
        ‘tempdb’.
        1> create table dept(dept_id int unique not null, dept_name varchar(100) null)
        2> go
        因为学生信息表students没有成功创建,执行第二遍语句,
        1>
        2>
        3>
        4> use tempdb
        5> go
        1> create table students ( id int not null,name varchar(30) null,
        2> dept_id int not null,constraint fk_students_dept_id foreign key(dept_id) references dept(dept_id) )
        3> go
        1> create table dept(dept_id int unique not null, dept_name varchar(100) null)
        2> go
        Msg 2714, Level 16, State 1:
        Server ‘NMR’, Line 1:
        There is already an object named ‘dept’ in the database.
        第二遍执行语句的时候,报部门信息表已经存在的错误。

        第二种情况:带if exitsts …. drop table …
        执行效果如下:
        1> use tempdb
        2> go
        1> if exists(select 1 from sysobjects where type=’U’ and name=’student’)
        2> drop table students
        3> go
        1> create table students ( id int not null,name varchar(30) null,
        2> dept_id int not null,constraint fk_students_dept_id foreign key(dept_id) references dept(dept_id) )
        3> go
        Msg 1710, Level 16, State 3:
        Server ‘NMR’, Line 1:
        Referenced table ‘dept’ specified in a referential constraint declared on
        ‘students’ does not exist in the database ‘tempdb’.
        Msg 2761, Level 16, State 4:
        Server ‘NMR’, Line 1:
        Failed to create declarative constraints on table ‘students’ in database
        ‘tempdb’.
        1>
        2> if exists(select 1 from sysobjects where type=’U’ and name=’dept’)
        3> drop table dept
        4> go
        1> create table dept(dept_id int unique not null, dept_name varchar(100) null)
        2> go
        1>
        2>
        3>
        4>
        5> use tempdb
        6> go
        1> if exists(select 1 from sysobjects where type=’U’ and name=’student’)
        2> drop table students
        3> go
        1> create table students ( id int not null,name varchar(30) null,
        2> dept_id int not null,constraint fk_students_dept_id foreign key(dept_id) references dept(dept_id) )
        3> go
        1>
        2> if exists(select 1 from sysobjects where type=’U’ and name=’dept’)
        3> drop table dept
        4> go
        Msg 3712, Level 16, State 1:
        Server ‘NMR’, Line 3:
        Cannot drop table ‘dept’ because it still has referential integrity
        constraints.
        1> create table dept(dept_id int unique not null, dept_name varchar(100) null)
        2> go
        Msg 2714, Level 16, State 1:
        Server ‘NMR’, Line 1:
        There is already an object named ‘dept’ in the database.
        第一遍同样students不能成功创建,第二遍dept不能删除,因为存在引用它的表students,继而也不能再次创建。

        PS:如果存在表之间的引用,且表之间的顺序不正确的话,需要将脚本执行两便才能保证对象都成功创建上。

    :wink: :twisted: :roll: :oops: :mrgreen: :lol: :idea: :evil: :cry: :arrow: :?: :-| :-x :-o :-P :-D :-? :) :( :!: 8-O 8)