PHP利用反射升级数据库结构

         用自己开发的php框架,是一个短期内可能很爽,长期来看,当开发人数和代码规模上升的时候,很痛苦的选择。使用文档、单元测试、代码生成工具、性能优化、Log和Debug等基础设施的建设将极大的消耗你的精力,让你无法专心于真正的业务上。

         公司开发的系统是一套SaaS的建站系统,架构上是所有客户使用同一套代码,但是每个站点有自己独立的数据库。而我们的系统开发时一个迭代的过程,开发新功能难免会对数据库做一些修改,比如:加一张新表,加一个新字段。对于我们这样的系统需要将所有客户的数据库都做数据库的改动。    

         第一阶段:我们使用最原始的方法,代码上线前,手动让运维将所有客户的表进行更新,然后上传代码。但是我们知道这个方法不是长久之计,于是很快我们就进入了第二阶段。

         第二阶段:sql文件+version,每次需要变动表结构,新建一个sql文件,文件名为site1.sql、site2.sql... 以此类推,我们会在每个站点自己的表里保存一个version字段,初始值为1,每次客户访问时自动运行最新的sql文件,并更新version值,保证不会重复执行相同的sql文件。这个方法很有效,后来我们的业务上来了,开发的新功能越来越多,sql文件疯狂上涨,突然我们发现每天总有些站点表里version增加,但是表里没有新增的表或字段,导致访问报错,影响很大。有一个同事为了保证不会再报错,在用到这张表的php语句前都加上创建语句。于是其他同事纷纷效仿,我们进入第三阶段。

       第三阶段:直接在使用php中加入修改sql,一开始是配合第二阶段一起用的,渐渐的,第二阶段的sql文件方式被抛弃了。这个方式的弊端也出现了:

       1. 性能上,修改表结构的sql,被重复执行,只有第一次是有效的。

       2. 开发上,当修改的表在多个地方使用,每个地方都需要加修改表结构的sql,很容易遗漏,导致程序出错。

       于是为了解决以上两个问题,于是我负责开发了第四代的升级数据库结构的方式,在方便使用的同时解决第三阶段的弊端。

       在这个方案中,第一步:我们创建一个Tbfix类,修改表结构的sql以表为单位拆分,分别写在这个类的不同的函数中,函数名为fix_加上表名,比如:有张表ss_image_resources的升级创建写在函数fix_image_resources函数中,并且统一提供对外接口Tbfix::fix($tablename),这个代码根据表名利用PHP反射机制自动执行对应函数。

      代码地址如下:

http://git.oschina.net/jamesren_781/5azrsv4ow98gijxeqhmfu.code.git

       第二步:利用mysql_query执行错误sql语句会return false的原理,我们在数据库访问封装类Mysql中,在增、删、改、查函数中加入判断,当mysql_query函数return false,利用Tbfix::fix($tablename)升级对应的表结构,然后重新执行函数。

以查询数据库函数为例,调用代码如下:

public function findAll($table_name,$params = array(),$where = '',$orderby='')
{
    
    // 通过参数拼接sql语句,省略。。。
    $res = mysql_query($_sql,$this->conn);

    if($res === false)
    {
        $ret=Tbfix::fix($table_name); //查询语句报错,尝试修复对应的表
        if(!$ret){
            $this->halt('Select is failed.',$_sql);
            return false;
        }else{
            return $this->findAll($table_name,$params ,$where,$orderby);//修复成功,重新执行函数
        }
    }
    
    while($row = mysql_fetch_array($res, RSTYPE_MYSQL))
    {
        $return[] = $row;
    }
    //释放数据库结果集
    mysql_free_result($res);
    return $return;
}

        通过这种方式保证了升级逻辑执行的自动化和执行效率相对最优化,既方便了开发者,也提高了性能。

        这个方案已经在实践之中,未来会继续根据实践结果去做修改,所有的方案都不是万能的,我觉得重要的是不断改进优化从而找到当前最合适自己的方案。路漫漫其修远兮,吾将上下而求索。

转载于:https://my.oschina.net/jamesren/blog/714310

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值