记录程序日志的三种选择
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记录程序日志的三种选择相关的知识,希望对你有一定的参考价值。
参考技术A 1、采用Log4CXX等公共开源日志组件:这类日志组件的特点是跨平台且功能比较强大,例如可以把日志发往另一台服务器或记录到数据库中等;另外,可配置性较高,可以通过配置文件或程序代码对日志进行很多个性化设置。但从另外一个角度看,由于这些优点往往也导致了在使用方面的缺点。首先,对于一般应用程序来说,它们并不需要太多的功能,通常只需要把日志记录到文件或反馈到应用程序,功能太多反正让用户使用起来觉得繁琐还得背负很多从来都用不到的代码。其次,这类日志组件通常是跨平台的,并不只是针对 Windows 或 VC 的`应用程序,因此使用起来总会觉得有点别扭,例如他们的字符都是用 char 类型的,对于一个 Unicode 程序来说每次写日志都要做字符转换是很不爽的事情,本座在多年前曾经使用过 Log4Cpp ,程序执行时总是报告日志组件有内存泄露,虽然有可能是误报,但是使用起来总觉得很不舒服。2、自己写几个简单的类或函数记录日志:这种方法的确很简单,通常都不用一两百行的代码。但这种方法通常缺乏规范性和通用性,其他程序需要记录类似的但有点差异的日志时,通常的作法是:Copy-Paste-Modify;另外,这类方法很可能也没有考虑性能或并发方面的问题,通常是直接在工作线程中写日志,对于那些性能要求较高的应用程序是绝对不允许的。
3、干脆不记录任何日志:的确,现在很多程序由于各种原因并没有记录任何日志。但本座以为,如果一个程序是有用的,具备一定功能,并且需要连续运行较长一段时间,那么记录日志是必须的;否则,得认真考虑该程序是否有存在的必要了。
MySQL日志binlog的三种模式
1 三种模式的介绍
二进制日志binlog作用:
1、以二进制形式记录更改数据库的SQL语句(insert,update,delete,create,drop,alter等)
2、用于Mysql主从复制
3、增量数据库备份及恢复
1.1 Row模式
日志会记录成每一行数据被修改成的形式,然后再slave端再对相同的数据进行修改,只记录要修改的数据,只有value,不会有sql多表关联的情况。
优点:在row模式下,bin-log中可以不记录执行的sql语句的上下文相关信息,仅仅需要记录哪一条记录被修改了,修改成什么信样了,所以row的日志内容会非常清楚的记录下每一行数据修改的细节,非常容易理解。而且不会出现在某些特定情况下的存储过程和function,以及trigger的调用和处罚无法被正确复制问题。
缺点:在row模式下,所有执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容。比如有这样一条update语句:updateproduct set name=‘gongli‘ 这条语句不是记录的一条,而是修改每一条的都会记录下来
1.2 Statement模式
每一条会修改数据的sql都会记录到master的binlog中,slave在复制的时候sql进程会解析成和原来master端相同的sql再执行。
优点:在Statement模式下首先就是解决了row模式下的缺点,不需要记录记录每一行日志的变化,减少了bin-log日志量,节省了I/O以及存储资源,提高性能。因为它们只需要激励在master上所执行的语句的细节以及执行语句时候的上下文信息。
缺点:在Statement模式下,由于它记录的执行语句,所以,为了让这些语句在slave端也能正确执行,那么它还必须记录每条语句在执行的时候的一些相关信息,也就是上下文信息,以保证所有语句在slave端被执行的时候能够得到和在master端执行时候的结果。另外,由于MySQL现在发展较快,很多的新功能不断的加入,使MySQL的复制遇到了不小的挑战,自然复制的时候涉及到越复杂的内容,bug也就越容易出现。在Statement中,目前已经发现不少情况会造成MySQL的复制出现问题,主要是修改数据的时候使用了某些特定的函数或者功能的时候会出现。比如:sleep()函数在有些版本中就不能直接复制,在存储过程中使用了last_insert_id()函数,可能会使slave和master上得到不一致的id等等。由于rowlevel是基于每一行来记录的变化,所以不会出现类似的问题
1.3 Mixed模式
从官方文档中看到,之前的MySQL一直都只有基于Statement的复制模式,知道5.1.5版本的MySQL才开始支持row模式。从5.0开始,MySQL的复制已经解决了大量老版本中出现的无法正确复制的问题。但是由于存储过程的出现,给MySQL replication又带来了更大的挑战。另外,看到官方文档说,从5.1.8版本开始,MySQL提供了除Statement和row之外的第三种模式:mixed,实际上就是前两种模式的结合。在mixed模式下,MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在Statement和row之间选择一种。新版本中的Statement还是和以前一样,仅仅记录执行的语句。而新版本的MySQL中对row模式也做了优化,并不是所有的修改都会以row模式来记录,比如遇到表结构变更的时候就会以Statement模式来记录,如果sql语句确实是update或者delete等修改数据的语句,那么还是会记录所有行的变更。
2 小结
Statement:
优点:记录的简单,内容少
缺点:导致主从不一致
例:
100w条记录
updatetest set name=‘tintin‘;
binilog 里面就只用update test set name=‘tintin‘;
ROW 行级模式
优点:记录数据详细(每行),主从一直
缺点:占用大量的磁盘空间,降低了磁盘的性能
100w条记录
updatetest set name=‘tintin‘;
binilog 里面就用100w条update test set name=‘tintin‘;语句
MIXED混合模式
100w条记录
updatetest set name=‘tintin‘;
binilog 里面就只用update test set name=‘tintin‘;
对于函数,触发器,存储过程
会自动的使用row-level模式
1 实战操作
1.1 要想mysql能用三种模式,必须开启binlog功能
[[email protected] ~]# mysql -uroot -p789 -S/data/3306/mysql.sock -e "show variables like ‘%log_bin%‘;"
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| log_bin | ON |
| log_bin_trust_function_creators | OFF |
| sql_log_bin | ON |
+---------------------------------+-------+
配置文件里面配置
[[email protected] ~]# egrep "log-bin"/data/3306/my.cnf
log-bin = /data/3306/mysql-bin
1.2 查看当前的binlog日志模式
[[email protected] ~]# mysql -uroot -p789 -S/data/3306/mysql.sock -e "show variables like ‘%binlog_format%‘;"
+---------------+-----------+
| Variable_name | Value |
+---------------+-----------+
| binlog_format | STATEMENT|
+---------------+-----------+
1.3 演示操作
1.3.1 查看当前的binlog文件
[[email protected] 3306]# ls
data mysql-bin.000001 mysql-bin.000004 mysqld.pid
my.cnf mysql-bin.000002 mysql-bin.000005 mysql_oldboy3306.err
mysql mysql-bin.000003 mysql-bin.index mysql.sock
[[email protected] 3306]# mysqlbinlog mysql-bin.000005
1.3.2 使用mysqlbinlog来查看二进制的binglog文件
[[email protected] 3306]# mysqlbinlog mysql-bin.000005
.......................... 省略部分
# at 7310
#160828 17:14:42 server id 1 end_log_pos 7337 Xid = 257
COMMIT/*!*/;
DELIMITER ; 这里就是sql语言
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 [email protected]_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
1.3.3 模仿操作
update一条数据
mysql> select * from test2;
+----+--------+
| id | name |
+----+--------+
| 1 | oldboy|
| 2 | gongli|
| 3 |inca |
| 4 |sb |
| 5 |kaka |
| 6 |doubi |
+----+--------+
6 rows in set (0.00 sec)
mysql> update test2 set name="laowang"where id=5;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from test2;
+----+---------+
| id | name |
+----+---------+
| 1 |oldboy |
| 2 |gongli |
| 3 |inca |
| 4 |sb |
| 5 |laowang |
| 6 |doubi |
+----+---------+
6 rows in set (0.00 sec)
查看binlog日志记录
[[email protected] 3306]# mysqlbinlog mysql-bin.000005
# at 7610
#160828 22:39:12 server id 1 end_log_pos 7717 Query thread_id=32 exec_time=0 error_code=0
SET TIMESTAMP=1472395152/*!*/;
update test2 set name="laowang" whereid=5
/*!*/;
# at 7717
#160828 22:39:12 server id 1 end_log_pos 7744 Xid = 299
COMMIT/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 [email protected]_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
1.4 row模式演示
1.4.1 修改binlog为row模式
mysql> show variables like ‘binlog_format‘;
+---------------+-----------+
| Variable_name | Value |
+---------------+-----------+
| binlog_format | STATEMENT |
+---------------+-----------+
1 row in set (0.02 sec)
mysql> set global binlog_format = ‘ROW‘;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like ‘binlog_format‘;
+---------------+-----------+
| Variable_name | Value |
+---------------+-----------+
| binlog_format | STATEMENT |
+---------------+-----------+
1 row in set (0.00 sec)
mysql> show global variables like‘binlog_format‘;
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+
1 row in set (0.00 sec)
临时修改:
mysql> set global binlog_format =‘ROW‘;
永久修改:
修改my.cnf配置文件
1.4.2 对表进行操作
update表test2
mysql> select * from test2;
+----+---------+
| id | name |
+----+---------+
| 1 |oldboy |
| 2 |gongli |
| 3 |inca |
| 4 |sb |
| 5 |laowang |
| 6 |doubi |
+----+---------+
6 rows in set (0.00 sec)
mysql> update test2 setname=‘dadou‘;
Query OK, 6 rows affected (0.00 sec)
Rows matched: 6 Changed: 6 Warnings: 0
mysql> select * from test2;
+----+-------+
| id | name |
+----+-------+
| 1 | dadou|
| 2 | dadou|
| 3 | dadou|
| 4 | dadou
1.4.3 查看binlog日志文件
[[email protected] 3306]# ls
data mysql mysql-bin.000005 mysql-bin.000007 mysql-bin.index mysql_oldboy3306.err
my.cnf mysql-bin.000004 mysql-bin.000006 mysql-bin.000008 mysqld.pid mysql.sock
[[email protected] 3306]# mysqlbinlog mysql-bin.000008
BINLOG ‘
GP3CVxMBAAAAMQAAAJ0CAAAAACMAAAAAAAEABm9sZGJveQAFdGVzdDIAAgP+Av48AA==
GP3CVxgBAAAAogAAAD8DAAAAACMAAAAAAAEAAv///AEAAAAGb2xkYm95/AEAAAAFZGFkb3X8AgAA
AAZnb25nbGn8AgAAAAVkYWRvdfwDAAAABGluY2H8AwAAAAVkYWRvdfwEAAAAAnNi/AQAAAAFZGFk
b3X8BQAAAAdsYW93YW5n/AUAAAAFZGFkb3X8BgAAAAVkb3ViafwGAAAABWRhZG91 这里我们会看到这些编码
‘/*!*/;
# at 831
#160828 23:02:48 server id 1 end_log_pos 858 Xid = 12
COMMIT/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 [email protected]_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
查看row模式下的编码
mysqlbinlog --base64-output="decode-rows"--verbose mysql-bin.000008
再次查看
mysqlbinlog --base64-output="decode-rows"--verbose mysql-bin.000008
........................省略一部分
### SET
### @1=5
### @2=‘dadou‘
### UPDATE `oldboy`.`test2`
### WHERE
### @1=6
### @2=‘doubi‘
### SET 这里就是上面代码翻译出来的东
### @1=6 我们看到这里是一条一条的记录的
### @2=‘dadou‘
# at 831
#160828 23:02:48 server id 1 end_log_pos 858 Xid = 12
COMMIT/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 [email protected]_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
本文出自 “圈中一鸟” 博客,请务必保留此出处http://sgk2011.blog.51cto.com/1551358/1843651
以上是关于记录程序日志的三种选择的主要内容,如果未能解决你的问题,请参考以下文章