基于名字自动发布之数据库(4)

原创
2018/08/21 17:24
阅读数 176

基于名字自动发布之数据库(4)

项目地址: https://gitee.com/lookingdreamer/RexDeploy_v1

流程图

几个重要的表

数据库表主要包含以下7个表

表名 说明
pre_auto_configure 配置模板关联表
pre_auto_template_vars 配置模板表
pre_bwzzbmonitor 监控信息表
pre_deploy_manage 自动发布信息记录表
pre_deploy_status 自动发布状态表
pre_external_server_detail CMDB主机配置外网表
pre_server_detail CMDB主机配置表

这7个表中最关键的是CMDB主机配置表pre_server_detail,所有名字服务关联的自动发布等都从这个表中取关键信息。

  • pre_server_detail

     涵盖了很多方面的记录,比如工程路径、进程、容器路径等可以作为建设cmdb的度量参考值

  • pre_deploy_manage

     发布前中后的相关统计,比如发布前应用的目录,发布的时间,启动的时间,发布是否成功等,可以用来分析发布数据,作为dashboard

  • pre_deploy_status

     发布状态表

perl DB demo

#查询
sub query {
    my ($env,$sql) = @_;
    if ( "$sql" eq "" ) {
        Rex::Logger::info("SQL不能为空","error");
        return;
    }
    my $dbh = init($env);
    $dbh->do('set SESSION wait_timeout=72000');
    $dbh->do('set SESSION interactive_timeout=72000');
    $dbh->do("SET NAMES utf8"); 
    my $sth = $dbh->prepare($sql);
    $sth->execute() or die( $sth->errstr );
    my @return;
    while ( my $row = $sth->fetchrow_hashref ) {
      push @return, $row;
    }    
    $sth->finish();
    $dbh->disconnect();
    return @return;
};

#初始数据库
sub init{
    my $env = $_[0]; 
    my $dbname;
    my $dbhost;
    my $dbuser;
    my $dbpassword;
    my $dbport;   

    Rex::Config->register_config_handler("$env", sub {
     my ($param) = @_;
      $dbname = $param->{dbname} ;
      $dbhost = $param->{dbhost} ;
      $dbuser = $param->{dbuser} ;
      $dbpassword = $param->{dbpassword} ;
      $dbport = $param->{dbport} ;
    });
    Rex::Logger::info("初始化$env环境数据库 host: $dbhost dbname: $dbname");
    my $dbh = DBI->connect("DBI:mysql:database=$dbname;host=$dbhost;port=$dbport",
                       "$dbuser", "$dbpassword",
                       {'RaiseError' => 1, 'AutoCommit' => 1 ,'mysql_auto_reconnect'=>1});
    return $dbh;
}

问题总结

1. 中文编码

问题

因为CMDB中保存中文,有时候查询出的数据是乱码.

解决问题

$dbh->do("SET NAMES utf8");

2. mysql has gone away

问题

在进行查询的时候,偶尔出现mysql has gone away的报错,尤其是进行多进程查询的时候

分析问题

mysql服务端是正常工作的,问题是偶尔出现.

  1. mysql宕机

       然而并没有,因为通过命令行去查询也是正常的(pass)

     2. 连接超时

       通过show global variables like '%wait_timeout'; wait_timeout被设置为3600秒,我执行也就几分钟的时间,不可能超过这个时间被服务端关闭.(pass)

     3. 被kill

      基本不可能,这台数据库就我一个用户,当然我也查询了show global status like 'com_kill',然而并没有.(pass)

     4. 执行sql太大了

     有可能你在导入大语句的时候有可能会出现这种情况,通过添加maxallowedpacket即可解决.但在这里我只是简单的查询数据.基本上没有多大的数据量. (pass)

 

折腾以上都么找到原因,么办法只能去啃源码和debug了. 源码有以下关键字段… 想要去看源码文件的请撮

use vars qw(@EXPORT $dbh);

@EXPORT = qw(db);
......
sub import {
........
  if ($opt) {
    $dbh = DBI->connect(
      $opt->{"dsn"}, $opt->{"user"},
      $opt->{"password"} || "", $opt->{"attr"}
    );
    $dbh->{mysql_auto_reconnect} = 1;
  }
......
}

原来是这样…

rex在执行任何模块之前会进行初始化模块,同时也包含数据库的初始化,数据库初始化之后会通过Var保存初始化的$dbh变量,以供之后的程序使用.但是从初始化变量开始到真正使用这中间隔了一段时间,同时我在更新字段之后添加了disconnect,一旦更新字段之后,原有的数据库链接其实不存在了.但是数据库初始化的变量还在,程序就以为该数据库连接当前还是可用的,于是就报mysql has gone away

我想本来作者也是想充分的利用数据库的连接,就相当于你开1个MYSQL终端去进行数据库操作,你之后的SQL操作都在这个终端上操作,不用的时候暂时挂起终端.使用的时候,再来打开,这样使用起来虽然方便,利用率也很高.但是这个复用链接的方式不是很可取,将复用链接保存到内存.关闭连接的时候数据也没有销毁,也没有重新创建.

补充一个问题: mysql_auto_reconnect 只有在DBD::mysql 4.012以后才支持

解决问题

目前我项目中采取很简单直接的方法: 每次进行数据库操作的时候,会重新连接数据库进行操作,同时异常连接的时候会重试几次数据库连接。当然这样对数据库会带来一定的压力,但是我的数据量很小,所以我就没花大力气去重新修改源码了(我承认我的方法太低端了)

更好的解决方法当然是引入数据库连接池,如java中的c3p0的连接池.perl MYSQL db也有它自己的数据库连接池。可以参考: DBIx::Connector

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部