关于log4net连接数据问题,开启日志服务器超过24小时后无法连接到mysql数据库

时间:2022-09-23 15:42:43
远程日志服务器启动超过24小时后将无法向mysql数据库插入数据,是什么原因呢?是数据库设置还是log4net设置问题呢?我用的最新版本的mysql.dll

配置参数
<configuration>
  <!-- Register a section handler for the log4net section -->
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
  </configSections>
  <!-- This section contains the log4net configuration settings -->
  <log4net>
    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger (%property{log4net:HostName}) - %message - account_id:%property{account_id} - role_id :%property{role_id} - action_type : %property{action_type}- %newline" />
      </layout>
    </appender>
    <appender name="LogFileAppender" type="log4net.Appender.FileAppender">
      <file value="log-file.txt" />
      <appendToFile  value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date account_id => %property{account_id} || role_id => %property{role_id} || role_name =>  %property{role_name} || server_id =>  %property{server_id} || action_type => %property{action_type} || action_value => %property{action_value} || extra_data => %property{extra_data} %newline" />
      </layout>
    </appender>
    <appender name="AdoNetAppender_MySql" type="log4net.Appender.AdoNetAppender">
      <bufferSize value="0" />
      <param name="ConnectionType" value="MySql.Data.MySqlClient.MySqlConnection, MySql.Data" />
      <param name="ConnectionString" value="server=localhost;database=xy2_web_transit;Uid=root;Pwd=1234562312;Charset=utf8;" />
      <!--<commandText value="INSERT INTO xy2_game_log(log_datetime,log_account_id,log_role_id,log_role_name,log_server_id,log_action_type,log_action_value,log_extra_data) VALUES (@log_date,@account_id,@role_id,@role_name,@server_id,@action_type,@action_value,@extra_data)"/>-->
      <commandText value="call InsertGameLog (@log_date,@account_id,@role_id,@role_name,@server_id,@action_type,@action_value,@extra_data)" />
      <parameter>
        <parameterName value="@log_date" />
        <dbType value="DateTime" />
        <layout type="log4net.Layout.RawTimeStampLayout" />
        <layout type="log4net.Layout.PatternLayout" value="%date{yyyy'-'MM'-'dd HH':'mm':'ss}" />
      </parameter>
      <parameter>
        <parameterName value="@account_id" />
        <dbType value="String" />
        <size value="32" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%property{account_id}" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@role_id" />
        <dbType value="String" />
        <size value="32" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%property{role_id}" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@server_id" />
        <dbType value="String" />
        <size value="32" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%property{server_id}" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@action_type" />
        <dbType value="String" />
        <size value="10" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%property{action_type}" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@action_value" />
        <dbType value="String" />
        <size value="500" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%property{action_value}" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@extra_data" />
        <dbType value="String" />
        <size value="1500" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%property{extra_data}" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@role_name" />
        <dbType value="String" />
        <size value="50" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%property{role_name}" />
        </layout>
      </parameter>
    </appender>
    <root>
      <level value="ALL" />
      <appender-ref ref="ConsoleAppender" />
      <appender-ref ref="AdoNetAppender_MySql" />
      <appender-ref ref="LogFileAppender" />
    </root>
  </log4net>
  <system.runtime.remoting>
    <application name="Log4netRemotingServer">
      <!-- We need to define the remoting channels on which we will publish
           the remote logging sink. -->
      <channels>
        <channel displayName="Server Channel" ref="tcp server" port="8085" />
      </channels>
    </application>
  </system.runtime.remoting>
  <system.data>
    <DbProviderFactories>
      <remove invariant="MySql.Data.MySqlClient" />
      <add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
    </DbProviderFactories>
  </system.data>
</configuration>

后台代码
   public class RemotingServer
    {
        // Create a logger for use in this class
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        /// <summary>
        /// Application entry point
        /// </summary>
        /// <param name="args">command line arguments</param>
        static void Main(string[] args)
        {
            // Log an info level message
                Console.WriteLine("Application [RemotingServer] Start");

            // Configure remoting. This loads the TCP channel as specified in the .config file.
            RemotingConfiguration.Configure(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);

            // Publish the remote logging server. This is done using the log4net plugin.
            log4net.LogManager.GetRepository().PluginMap.Add(new log4net.Plugin.RemoteLoggingServerPlugin("LogOperator"));

            // Wait for the user to exit
            Console.WriteLine("Press 0 and ENTER to Exit");
            String keyState = "";
            while (String.Compare(keyState, "0", true) != 0)
            {
                keyState = Console.ReadLine();
            }

            // Log an info level message
            if (log.IsInfoEnabled) log.Info("Application [RemotingServer] End");
        }
    }

12 个解决方案

#1


贴出vs调试器在捕获异常时的画面,画面上包括你在此时对变量的调试。

#2


没有异常的画面,我只能在控制台输出的时候,发现数据库没有插入数据,刚启动24小时内都可以的,我怀疑是数据库设置的问题

#3


关于log4net连接数据问题,开启日志服务器超过24小时后无法连接到mysql数据库关于log4net连接数据问题,开启日志服务器超过24小时后无法连接到mysql数据库还有谁知道呢?求帮忙呀!

#4


引用 2 楼 cuichaoping 的回复:
没有异常的画面,我只能在控制台输出的时候,发现数据库没有插入数据,刚启动24小时内都可以的,我怀疑是数据库设置的问题

1、执行数据库插入的代码没有抛出异常么?
2、不用log4net,单独运行程序,24小时之后看运行正常么?

#5


无法连接到有报异常吗?

#6


看不到抛异常,问题的关键就在这里,我在本机测试24小时都没有问题,你没有做过log4net吧!我log4net是远程服务器,客户端发送信息我控制台都能收到,只是过了24小时后数据库插入不进去,所以我只能怀疑数据库问题,数据库所以的配置参数在xml里面,根本就抛不了异常,我怀疑是数据库超时的问题

#7


强调下,我是楼主

#8


你可以看mysql的日志啊,是不是把log4net那台的连接给断了

#9


遇到同样的问题楼主是怎么解决的?

#10


找一下异常日志,Log4net或者 mysql的

#11


这个问题主要是Mysql会把空闲8小时(wait_timeout默认值为28800秒)没有操作的数据库连接给主动断开,由于晚上没有操作造成log4net长时间没有记录日志,mysql把数据库连接断开了,到第二天白天开始写日志时由于数据库连接状态部位打开状态而被跳过了记录操作,
在github上下载了log4net的源码发现有一个“ReconnectOnError”的参数意图是在数据库连接异常时是否重新连接,在构造函数中设置了默认值为false,错误不重连


public class AdoNetAppender : BufferingAppenderSkeleton
{
#region Public Instance Constructors

/// <summary> 
/// Initializes a new instance of the <see cref="AdoNetAppender" /> class.
/// </summary>
/// <remarks>
/// Public default constructor to initialize a new instance of this class.
/// </remarks>
public AdoNetAppender()
{
m_connectionType = "System.Data.OleDb.OleDbConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
m_useTransactions = true;
m_commandType = System.Data.CommandType.Text;
m_parameters = new ArrayList();
m_reconnectOnError = false;
}

private bool m_reconnectOnError;
……
public bool ReconnectOnError
{
get { return m_reconnectOnError; }
set { m_reconnectOnError = value; }
}
……
override protected void SendBuffer(LoggingEvent[] events)
{
if (m_reconnectOnError && (m_dbConnection == null || m_dbConnection.State != ConnectionState.Open))
{
LogLog.Debug(declaringType, "Attempting to reconnect to database. Current Connection State: " + ((m_dbConnection==null)?SystemInfo.NullText:m_dbConnection.State.ToString()) );

InitializeDatabaseConnection();
InitializeDatabaseCommand();
}

// Check that the connection exists and is open
if (m_dbConnection != null && m_dbConnection.State == ConnectionState.Open)
{
if (m_useTransactions)
{
// Create transaction
// NJC - Do this on 2 lines because it can confuse the debugger
IDbTransaction dbTran = null;
try
{
dbTran = m_dbConnection.BeginTransaction();

SendBuffer(dbTran, events);

// commit transaction
dbTran.Commit();
}
catch(Exception ex)
{
// rollback the transaction
if (dbTran != null)
{
try
{
dbTran.Rollback();
}
catch(Exception)
{
// Ignore exception
}
}

// Can't insert into the database. That's a bad thing
ErrorHandler.Error("Exception while writing to database", ex);
}
}
else
{
// Send without transaction
SendBuffer(null, events);
}
}
}
}

解决方案:
方案1、把mysql的wait_timeout设置长一些具体多长根据自己实际需求;
方案2、在log4net的配置文件中添加一行“<param name="ReconnectOnError" value="true"/>”,如下
<appender name="AdoNetAppender_MySql" type="log4net.Appender.AdoNetAppender">
      <bufferSize value="0" />
      <param name="ConnectionType" value="MySql.Data.MySqlClient.MySqlConnection, MySql.Data" />
      <param name="ConnectionString" value="server=localhost;database=xy2_web_transit;Uid=root;Pwd=1234562312;Charset=utf8;" />
  <param name="ReconnectOnError" value="true"/>
  ……
</appender>

方案3、下log4net载源码修改掉ReconnectOnError的默认值;

#12


学习了。大概大晚上的没人操作了,估计上到生产环境就不会再出问题了哦

#1


贴出vs调试器在捕获异常时的画面,画面上包括你在此时对变量的调试。

#2


没有异常的画面,我只能在控制台输出的时候,发现数据库没有插入数据,刚启动24小时内都可以的,我怀疑是数据库设置的问题

#3


关于log4net连接数据问题,开启日志服务器超过24小时后无法连接到mysql数据库关于log4net连接数据问题,开启日志服务器超过24小时后无法连接到mysql数据库还有谁知道呢?求帮忙呀!

#4


引用 2 楼 cuichaoping 的回复:
没有异常的画面,我只能在控制台输出的时候,发现数据库没有插入数据,刚启动24小时内都可以的,我怀疑是数据库设置的问题

1、执行数据库插入的代码没有抛出异常么?
2、不用log4net,单独运行程序,24小时之后看运行正常么?

#5


无法连接到有报异常吗?

#6


看不到抛异常,问题的关键就在这里,我在本机测试24小时都没有问题,你没有做过log4net吧!我log4net是远程服务器,客户端发送信息我控制台都能收到,只是过了24小时后数据库插入不进去,所以我只能怀疑数据库问题,数据库所以的配置参数在xml里面,根本就抛不了异常,我怀疑是数据库超时的问题

#7


强调下,我是楼主

#8


你可以看mysql的日志啊,是不是把log4net那台的连接给断了

#9


遇到同样的问题楼主是怎么解决的?

#10


找一下异常日志,Log4net或者 mysql的

#11


这个问题主要是Mysql会把空闲8小时(wait_timeout默认值为28800秒)没有操作的数据库连接给主动断开,由于晚上没有操作造成log4net长时间没有记录日志,mysql把数据库连接断开了,到第二天白天开始写日志时由于数据库连接状态部位打开状态而被跳过了记录操作,
在github上下载了log4net的源码发现有一个“ReconnectOnError”的参数意图是在数据库连接异常时是否重新连接,在构造函数中设置了默认值为false,错误不重连


public class AdoNetAppender : BufferingAppenderSkeleton
{
#region Public Instance Constructors

/// <summary> 
/// Initializes a new instance of the <see cref="AdoNetAppender" /> class.
/// </summary>
/// <remarks>
/// Public default constructor to initialize a new instance of this class.
/// </remarks>
public AdoNetAppender()
{
m_connectionType = "System.Data.OleDb.OleDbConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
m_useTransactions = true;
m_commandType = System.Data.CommandType.Text;
m_parameters = new ArrayList();
m_reconnectOnError = false;
}

private bool m_reconnectOnError;
……
public bool ReconnectOnError
{
get { return m_reconnectOnError; }
set { m_reconnectOnError = value; }
}
……
override protected void SendBuffer(LoggingEvent[] events)
{
if (m_reconnectOnError && (m_dbConnection == null || m_dbConnection.State != ConnectionState.Open))
{
LogLog.Debug(declaringType, "Attempting to reconnect to database. Current Connection State: " + ((m_dbConnection==null)?SystemInfo.NullText:m_dbConnection.State.ToString()) );

InitializeDatabaseConnection();
InitializeDatabaseCommand();
}

// Check that the connection exists and is open
if (m_dbConnection != null && m_dbConnection.State == ConnectionState.Open)
{
if (m_useTransactions)
{
// Create transaction
// NJC - Do this on 2 lines because it can confuse the debugger
IDbTransaction dbTran = null;
try
{
dbTran = m_dbConnection.BeginTransaction();

SendBuffer(dbTran, events);

// commit transaction
dbTran.Commit();
}
catch(Exception ex)
{
// rollback the transaction
if (dbTran != null)
{
try
{
dbTran.Rollback();
}
catch(Exception)
{
// Ignore exception
}
}

// Can't insert into the database. That's a bad thing
ErrorHandler.Error("Exception while writing to database", ex);
}
}
else
{
// Send without transaction
SendBuffer(null, events);
}
}
}
}

解决方案:
方案1、把mysql的wait_timeout设置长一些具体多长根据自己实际需求;
方案2、在log4net的配置文件中添加一行“<param name="ReconnectOnError" value="true"/>”,如下
<appender name="AdoNetAppender_MySql" type="log4net.Appender.AdoNetAppender">
      <bufferSize value="0" />
      <param name="ConnectionType" value="MySql.Data.MySqlClient.MySqlConnection, MySql.Data" />
      <param name="ConnectionString" value="server=localhost;database=xy2_web_transit;Uid=root;Pwd=1234562312;Charset=utf8;" />
  <param name="ReconnectOnError" value="true"/>
  ……
</appender>

方案3、下log4net载源码修改掉ReconnectOnError的默认值;

#12


学习了。大概大晚上的没人操作了,估计上到生产环境就不会再出问题了哦