基于名字自动发布之数据库(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服务端是正常工作的,问题是偶尔出现.
-
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