• 一个基于mysql数据库的项目的升级解决方案小结(节选)


    1  引言

    数据库使用MYSQL4.0版本。随用用户数的逐步增多,因为数据库版本过低而引起的抱怨也越来越多,不足也越来越明显。

    首先,对产品化部署产生了制约。由于MYSQL4.0数据库的配置文件my.ini是存放在Windows的系统目录下的,同时MYSQL4.0的安装程序无法对端口号进行设置。所以如果一个服务器上已经安装了任意一个版本MYSQL数据库,再安装一个MYSQL4.0,以前的MYSQL 数据库将无法使用。但是随着用户的日益增多,客户提供的服务器的软件环境也是各式各样。不可避免会出现客户提供的服务器上已经安装了MYSQL的情况,而目前系统只在MYSQL4.0上可以使用,所以只能和客户商量更换服务器来解决这个问题(目前已经有多家客户存在这种情况)。因此,如果要使得系统实现产品化部署, MYSQL4.0并不符合要求。另外,在MYSQL的官方网站上,已经停止对MYSQL4.0提供下载。一方面说明,MYSQL4.0已渐渐被淘汰;另一方面,MYSQL在未经开发商授权是不能被商用的[2]因此在实际的部署中,原则上数据库需要用户自行安装的,但安装包的官方下载地址已经不存在了,也会造成商业上的一些问题。所以MYSQL4.0是该系统产品化的一个瓶颈。

    其次,对多国语言支持功能弱。由于MYSQL4.0发布时间较早,只支持latin1编码方式存储,而不支持如UTF-8,GBK的编码存储。因此对于如VBVFP等对Unicode支持不够的编程语言而言,它们从MYSQL4.0数据库获取的中文或日文字符将成乱码显示。而目前一些客户会使用VB制作一些第三方工具来读取该系统的数据库,这个时候就会出现麻烦。

    再次,缺少数据库的必要功能。MYSQL4.0是不支持子查询,视图,存储过程等数据库高级特性的。随着系统功能的逐步增强,代码量的不断增加,不可避免会出现性能问题,而对以上这些高级特性的使用,正是解决性能问题的有效对策之一。所以这部分功能的缺失,是系统性能改善的一个瓶颈。

    还有,长字符存入数据库后有时会出现乱码。MYSQL4.0对各种类型的数据的定义不是很严格。特别是对字符型,由于是用latin1编码进行存储的,一个中文字符是按3个编码单位进行存储的,对于定义为varchar10的字段,如果存入4个中文字符的话,第4个中文字符将自动被截去三分之二。因此在数据库中,最后一个中文字符将丢失,同时在界面上显示乱码。更重要的是,这一个过程,数据库没有任何的警示。所以系统现在的系统中,用户的数据会在不知情的情况下丢失。这个也是系统客户使用时候的一个瓶颈。

    综合这四方面考虑,数据库的版本问题确实是今后系统发展的一个瓶颈。将系统的数据库进行升级是一个刻不容缓的事情。

    2  前期调查和迁移实验

     

    由于MYSQL4.0的诸多限制会影响产品的发展,因此本人受项目组委托,对MYSQL的升级方案进行了具体的调研和整理。(从20092月开始,到20094月中旬完成)

    整个调研工作将分成一下四个阶段进行:

    (1)前期调查准备

     MYSQL4.0以上各个版本进行考察,选择合适的MYSQL版本,和对应的JDBC版本

    (2)迁移实验

    按照先数据修改,再代码修改的顺序进行。并对实验的经验进行归纳,整理出迁移方案,并按照该方案部署Demo系统。

    (3)测试验证工作

    ①对Demo系统进行IT测试,确保迁移完成后的系统应用能够在新的数据库上正常运行,从而验证迁移工作是否成功。

    ②使用相同的Demo系统在MYSQL4.0上进行兼容性测试,确保修改后的 系统系统能够在MYSQL4.0上也能正常运行。

    (4)正式部署

    为了使该方案尽早投入实际的应用中,目前已经和一个需要进行数据库升级的国内客户达成协议,一旦前面4个阶段完成,将为该客户进行数据库升级。

    本章中将对第1阶段和第2阶段展开详细介绍:

     

    2.1  前期调查的成果

     

    2.1.1  数据库版本的选择

    经过对MYSQL官方网站相关资料的查询,确认在MYSQL4.0以上的主流版本包括4.15.05.1三个版本(截止20092月)[3]

    1的数据显示说明,MYSQL5.0以上版本已经能够解决上文中提到的四大瓶颈。另一方面,在升级方案提出后的较长一段时间内,会存在基于MYSQL4.0该系统和基于升级版本的该系统两者共存的情况。因此,经过升级改造后的程序需要在这两个版本上都能运行,所以程序需要对数据库版本有一定的兼容性。其中比较重要的JDBC的选择上,MYSQL5.1并不能满足要求,同时5.1的新特性也不是升级系统所必须的。因此,综合考虑后,MYSQL5.0是数据库升级最合适的目标版本。而5.0版本当时最新的小版本号为5.0.18,因此接下来的迁移工作将围绕MYSQL5.0.18进行。

    1 MYSQL三版本特性对比

         版本      特性

    MYSQL4.1

    MYSQL 5.0

    MYSQL 5.1

    官方网站是否

    提供下载

    是否支持多个

    my.ini共存

    是否支持多种

    编码存储

    长字符存入是否出现乱码

    引入新功能

    子查询;默认支持事务类型表

    视图,触发器,存储过程,分布式事务

    事件调度器,增强的日志功能

    是否能使用和

    4.0一样的JDBC

     

    2.1.2  JDBC的选择

    由于目前系统使用的JDBC2.0.4版本的,该版本只能支持MYSQL4.0,所以JDBC必须进行升级。但是,升级后的JDBC必须能够保证对MYSQL4.0MYSQL5.0的同时支持,因此JDBC5.0以上的版本可以不做考虑。剩下可以考虑的是3.03.1两个版本。其中3.0版本主要是针对4.04.1版本设计的,但对5.0版本的基本功能能够支持,但所有的新特性并不支持;3.1版本主要是针对4.15.0版本设计的,支持除分布式事务外的所有5.0的特性[4]。因此,选择3.1版本的JDBC更为理想。

     

    2.1.3  数据迁移方式的选择

    对于已经存在于MYSQL4.0中的老数据如何更新到MYSQL5.0中,这是一个比较关键的问题。可以采用的方法有三种:

    1直接复制数据文件

    2使用Dump命令

    3使用专业工具

    经过调查,方法2比较可行。按照方法1操作,发现数据库表中所有字符型的字段的长度都缩小为原来的三分之一,而且这些字段的长度无法进行再修改。这样的话,系统将无法正常使用。

    按照方法3,这类开源的工具暂时没有,即使存在非开源的这类工具,那数据迁移的成本也将大大提高,所以方法3也不可行。因此唯一可以行的是方法2

     

    2.2  迁移实验的成果

     

    2.2.1  迁移的准备

    在前期的调查工作完成后,就开始进入迁移的实际工作。

    首先安装好MYSQL4.0MYSQL5.0两个版本的数据库,其中MYSQL5.0在配置的时候需要将编码方式选择为UTF-8。并且准备好建库的原始脚本,和一份MYSQL4.0数据库下的真实数据拷贝。

    然后在 Tomcat下部署好合适的系统。由于v5.7.1版本是目前为止品质最稳定,功能上也比较完整的版本,因此我们尝试使用v5.7.1版作为迁移的程序版本。

    最后,将准备好JDBCmysql-connector-java-3.1.10-bin.jar)替换原来的JDBC

     

    2.2.2  迁移的具体方法

    整个实验主要分成两个阶段进行展开:

    系统全新部署的迁移实验;

    使用中的系统的迁移实验。

    两个阶段的迁移思路是一致的

     

     

    2.2.3  迁移的难点分析和解决

    按照2.2.2 的迁移方法逐步展开工作,问题一个个被发现,然后又一个个被妥善解决。但也遇到了一些困难,经过深入的分析和实践,这些问题最终获得了解决。解决这些问题的思路还是值得借鉴的,因此进行详细的介绍。

    难点一:

    MYSQL4.0中已被部分截断的字符型数据无法使用Dump命令导出。

    难点分析:

    该类数据在真实的数据拷贝版本中有2000多条,而且存在于多个表的多个字段中。理论上,只要是varchartext类型的字段都有发生该情况的可能性。而手工一条条的修改不是很现实的,所以必须找到规律和特征,才能解决该问题。对于任何客户,如果因为数据库的升级,而需要丢失数千条未知的数据,这种情况是无法接受的。

    通过对被截断的字符型数据的统计,发现并不是所有被截断数据都无法导出,只有截断后最后一个字符变成乱码的时候,才会无法导出。被截断是因为存入的数据是按照latin1方式存储的,一个中文字占三个字长,当总字长大于子段定义长度的时候,多余的字符将被截断。因此对于中文字,被截断的情况可以分成三类:

    l         中文字的三分之一编码被截去;

    l         中文字的三分之二编码被截去;

    l         中文字的全部编码被截去。

    第三类就是不出现乱码的情况,其他两类就会出现乱码。因此,理论上只要把出现乱码的字符串的最后一个或者最后两个编码去除,就可以将该字符串变成合法的字符串,然后就可以进行导出操作了。经过对大量乱码数据的分类归纳,发现这些乱码数据的最后第一个或者最后第二个字符是有规律的,它的ASCII码都大于191

    解决对策:

    制作相应的数据库数据乱码修正工具,对所有的varchartext类型的字段进行检测,如果发现数据的最后一个或者最后第二个字符的编码值大于191,就进行对应的截取,具体代码如下:

    update TableName set ColumnName=substring(ColumnName,1, DefineLength-2) where char_length(workName)=DefineLength and ASCII(RIGHT(ColumnName,2)) >191;

     

    update TableName set ColumnName=substring(ColumnName,1, DefineLength-1) where char_length(workName)=DefineLength and ASCII(RIGHT(ColumnName,1)) >191;

     

    难点二:

    JDBC3.1版本使用的问题。

    难点分析:

    按照2.1.3的思路,将原来的JDBC版本进行了替换。在迁移的实验中发现系统频繁出现“内存溢出”,“JSP无法编译”,“Servlet异常”等问题,导致系统无法正常运行。经过排查,发现问题出现在JDBC上,经过对3.1下所有小版本的验证,发现问题依旧存在。2.1.2节中曾提到,称3.0版的JDBC可以支持5.0MYSQL的基本功能,因此更换了当时的最新版本3.0.16版本进行尝试。经过验证,3.1下的所有问题都消失了,系统能够稳定运行了。

    但是,在迁移工作继续开展中发现了另一个问题:带参的SQL语句无法成功,但对应的SQL在命令行中是能够运行成功的。这表明了程序和数据库都是没有问题的,唯一的可能是问题出在JDBC上,有可能这个版本的JDBC不支持PreStatementSQL操作。但3.0.16是当时的最新版本了,3.1版本虽然是支持PreStatementSQL操作,但因为前面提到的问题而无法使用,这是否意味着,迁移工作无法完成呢?这时候,突然发现MYSQL官网上两天前发布了3.0的更新版本3.0.17[5]替换后验证,3.0.16上的问题解决了,同时3.1上的问题也没有再现。

    解决对策:

    使用3.0.17版本的JDBC作为该系统连接MYSQL5.0JDBC 经过验证,该JDBC也同时支持MYSQL4.0的连接。当然,如果不使用3.0.17版本的JDBC的话, SQL操作就需要修改为非PreStatement方式来执行了,这样的修改代价是比较大的。

     

    2.2.4  迁移的成果总结

    按照迁移的基本方法开展工作,同时对一些难点进行了成功的攻克,整个迁移实验取得了理想的成果。

    首先,证明了该系统MYSQL4.05.0进行迁移是可行的。既包括系统全新部署,也包括原有系统的升级。

    其次,在实验过程中,获取了MYSQL4.0MYSQL5.0在使用上差异性的汇总表,根据该汇总表可以对现有的数据库结构和程序进行修改;同时也可以指导开发人员在今后的开发中如何设计出同时符合MYSQL4.0MYSQL5.0要求的数据表结构,也能编写出满足这2种数据库要求的代码。具体的汇总表见表2

    2  MYSQL4.05.0功能差异对比

     

    MYSQL4.0

    MYSQL5.0

    int类型字段

    允许插入 ''

    不允许插入 '' ,只能插入 null

    int类型字段

    设置为非空,仍可以插入 null

    设置为非空,就不允许插入 null

    Float类型字段

    float(5,2)类型,可以输入任意浮点数

    当输入大于999.99的数时,抛出异常;

    Varchar类型字段

    标记为非空,可以不插入值;

    标记为非空,必须插入值;

    Varchar类型字段

    允许插入 ''

    不允许插入 '' ,只能插入 null

    Varchar类型字段

    varchar(99)只能存放33个中文字符

    varchar(99)能存放99个中文字符

    Varchar类型字段

    Varchar上限为255,

    varchar上限为1000

    Varchar类型字段

    空格不被计数

    空格被计数

    Varchar类型字段

    “/”不被计数

    “/”被计数

    Date类型字段

    0000-00-00合法

    0000-00-00不合法

    DateTime类型字段

    精确到0

    精确到0.1

    0能否强制转化为Number类型

    不能

    设置为联合主键的字段能否插入null

    不能

    联合索引的总容量

    无限制

    不能超过1000bytes

    自增长类型是否需要设置成key或索引

    Condition”是否可以作为字段名

    建表语句中

    表名两端的空格会自动过滤

    表名两端的空格不会自动过滤

    建表语句中

    最后一个字段后跟逗号,不会报错

    最后一个字段后跟逗号,会报错

    findRecord函数

    可以执行 insert操作

    不能执行 insert操作

    ResultSet.getObject函数

    获取数字类型为integer

    获取数字类型为long

    再次,系统代码对MYSQL5.0 的兼容性修改完毕。共修改49处问题,涉及45java文件;同时对该系统的建库脚本进行了完善,共修改了8SQL语句。

     

    3  解决方案总结及实例应用

     

    在完成迁移实验后,紧接着开展了测试验证工作。测试验证工作一方面补充和完善了迁移的成果,另一方面确保了升级后程序的稳定性和兼容性。从而一个完整的系统数据库升级方案已经形成。

     

    3.1  解决方案总结

    1.对于新部署的系统,方案相对简单:

    1)部署好MYSQL5.0,配置编码方式:UTF-8

    2执行修改后的建库脚本。

    3)将修改后的程序部署到Tomcat下,启动服务器。

    即完成了基于MYSQL5.0的新系统部署。

    2.对于旧系统从MYSQL4.05.0,具体方案如下:

    1停止旧的Web服务,保证升级过程中无新数据产生。

    2)执行数据库兼容性升级工具(修改不兼容的字段名,字段类型,字段的默认值,表的主键值,以及去除字符型数据中的乱码)

    3DumpMYSQL4.0中的数据文件

    4部署好MYSQL5.0,配置编码方式:UTF-8

    5将该数据文件导入MYSQL5.0中;

    6将修改后的程序部署到Tomcat下,启动服务器。

     

  • 相关阅读:
    聊聊click延迟和点击穿透
    setAttribute的浏览器兼容性(转)
    浅谈JS中的高级函数
    跨域总结
    本地存储小结
    ubuntu下pip的安装和使用
    并发编程艺术-锁类型以及底层原理
    HTTP协议以及HTTP2.0/1.1/1.0区别
    Paxos
    jvm垃圾收集器总结jdk1.7
  • 原文地址:https://www.cnblogs.com/superch0054/p/4010103.html
Copyright © 2020-2023  润新知