zoukankan      html  css  js  c++  java
  • bind9+dlz+mysql连接断开问题

    前言

    关于bind-dlz介绍:http://bind-dlz.sourceforge.net/

    DLZ(Dynamically Loadable Zones)与传统的BIND9不同,BIND的不足之处:

    1. BIND从文本文件中获取数据,这样容易因为编辑错误出现问题。
    2. BIND需要将数据加载到内存中,如果域或者记录较多,会消耗大量的内存。
    3. BIND启动时解析Zone文件,对于一个记录较多的DNS来说,会耽误更多的时间。
    4. 如果近修改一条记录,那么要重新加载或者重启BIND 才能生效,那么需要时间,可能会影响客户端查询。

    而Bind-dlz 即将帮你解决这些问题,对Zone文件操作也更方便了,直接对数据库操作,可以很方便扩充及开发管理程序。

    bind-dlz的相关配置就不说了,网上一大堆,推荐两个:

    问题描述

    bind9+dlz+mysql配置好正常使用没什么问题,但是当使用了一段时间(都是隔夜)之后再次解析之前的域名发现解析不了,查看日志/var/log/messages,发现如下错误信息:

    localhost named[42406]: mysql driver unable to return result set for findzone query
    

    经查询资料得知是因为dlz在连接mysql之后,由于连接的空闲时间达到mysql的最大空闲时间,被mysql强行断开导致无法再从mysql获取数据。关键是DLZ在断开之后不会重连,这就不得不重启named服务重新与mysql建立连接了。

    但明显这个办法不靠谱,想到的解决方案大概有下面几种:

    • 1.更换成其他数据库
    • 2.修改wait_timeout为更大值,24天左右
    • 3.重启named服务
    • 4.保持连接的使用,定期进行查询
    • 5.修改dlz源码,加入数据库重连功能

    更换数据库暂时不考虑;修改mysql的wait_timeout也不能解决根本问题;第3个就不说了;第四个我试了下,写了一个脚本定时请求bind解析域名,想让连接不超时,但是最后证明这种办法不行,不知道是不是方式不对;最后一种是实在没有办法了,硬着头皮打开了源码。。。

    解决方案

    。。。好吧,没有想象中的那么难,找到bind-9.6.0-P1/contrib/dlz/drivers/dlz_mysql_driver.c,大致读了下,配合资料 C中MySQL自动重新连接(部分zz),在dlz_mysql_driver.c的mysql_create函数中加入了重连的代码,完整函数内容:

    /*%
     * create an instance of the driver.  Remember, only 1 copy of the driver's
     * code is ever loaded, the driver has to remember which context it's
     * operating in.  This is done via use of the dbdata argument which is
     * passed into all query functions.
     */
    static isc_result_t
    mysql_create(const char *dlzname, unsigned int argc, char *argv[],
    	     void *driverarg, void **dbdata)
    {
    	isc_result_t result;
    	dbinstance_t *dbi = NULL;
    	char *tmp = NULL;
    	char *dbname = NULL;
    	char *host = NULL;
    	char *user = NULL;
    	char *pass = NULL;
    	char *socket = NULL;
    	int port;
    	MYSQL *dbc;
    	char *endp;
    	int j;
    	unsigned int flags = 0;
    	//新增部分:定义了一个value
    	char value = 1;
    
    	UNUSED(driverarg);
    	UNUSED(dlzname);
    
    	...
    
    	tmp = getParameterValue(argv[1], "space=");
    	if (tmp != NULL) {
    		if (strcasecmp(tmp, "ignore") == 0)
    			flags = flags | CLIENT_IGNORE_SPACE;
    		isc_mem_free(ns_g_mctx, tmp);
    	}
    
        //新增部分:重连的代码
    	/* reconnect to mysql */
    	result = mysql_options((MYSQL *)dbi->dbconn, MYSQL_OPT_RECONNECT, (char *)&value);
    	if( result != 0 )
    	{
    		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
    			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
    			      "mysql_options reconnect failed!");
    		result = ISC_R_FAILURE;
    		goto full_cleanup;
    	}
    	
    	dbc = NULL;
    	host = getParameterValue(argv[1], "host=");
    	user = getParameterValue(argv[1], "user=");
    	pass = getParameterValue(argv[1], "pass=");
    	socket = getParameterValue(argv[1], "socket=");
    
    	for (j=0; dbc == NULL && j < 4; j++)
    		dbc = mysql_real_connect((MYSQL *) dbi->dbconn, host,
    					 user, pass, dbname, port, socket,
    					 flags);
    
    	/* let user know if we couldn't connect. */
    	if (dbc == NULL) {
    		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
    			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
    			      "mysql driver failed to create "
    			      "database connection after 4 attempts");
    		result = ISC_R_FAILURE;
    		goto full_cleanup;
    	}
    
    	...
    }
    

    附上mysql关于c语言的官方文档: https://dev.mysql.com/doc/refman/5.6/en/mysql-real-connect.html

    改完之后重新编译安装就好了,经过测试,第二天来发现域名仍然可以正常解析。问题暂时解决,后面再观察一下。

  • 相关阅读:
    刚好遇见你——软件工程
    int main(int argc,char* argv[]) 简单理解
    奇偶数分离
    A+B Problem
    日期计算
    正三角形的外接圆面积
    数数小木块
    谁是最好的Coder
    水仙花数
    5个数求最值
  • 原文地址:https://www.cnblogs.com/nickhan/p/9849687.html
Copyright © 2011-2022 走看看