需求:把apache日志导入到mysql中
apache日志样例:
10.1.1.95 - e800 [18/Mar/2005:12:21:42 +0800] "GET /stats/awstats.pl?config=e800 HTTP/1.1" 200 899 "http://10.1.1.1/pv/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon)"
说明:
1. 10.1.1.95 远程主机的地址 2.浏览者的标识 3.e800记录浏览者进行身份验证时提供的名字 4.18/Mar/2005:12:21:42 +0800请求的时间 5."GET /stats/awstats.pl?config=e800 HTTP/1.1"方法 资源 协议 6.200状态代码 7.899发送给客户端的总字节数 8.客户在提出请求时所在的目录或URLhttp://10.1.1.1/pv/ 9.客户端的详细信息Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Maxthon)
整理出的字段
ip marking browser_name time time_zone method resource protocol status bytes refer client_info
建表语句
--
-- Table structure for table `apache_log`
--
CREATE TABLE IF NOT EXISTS `apache_log` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id号',
`hostip` char(32) NOT NULL DEFAULT '0.0.0.0' COMMENT '远程主机的地址',
`marking` char(30) COMMENT '浏览者的标识',
`browser_name` char(30) COMMENT '浏览者进行身份验证时提供的名字',
`addtime` char(64) NOT NULL COMMENT '请求的时间',
`time_zone` char(8) NOT NULL COMMENT '时区',
`method` char(8) NOT NULL COMMENT '方法',
`resource` char(64) NOT NULL COMMENT ' 请求的资源',
`protocol` char(8) COMMENT '请求使用的协议',
`status` int(5) COMMENT '状态代码',
`bytes` int(5) COMMENT '发送给客户端的总字节数',
`refer` char(128) COMMENT '客户在提出请求时所在的目录或URL',
`client_info` char(128) COMMENT '客户在提出请求时所在的目录或URL',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
解决方案:
先用awk处理apache日志,将每一项都用空格分开,那么大家看到下面的好多数字就迷惑了,这到底是个什么东西呢。我来慢慢讲解,首先awk '{print 0 ,像apache日志的文本中每行写入一个0,原因是,表结构的第一个字段是自增列,我只要把0导入,0表示默认值,它就可以自动增长了。
cat apache_log|awk '{print 0 " "$1 " "$2 " "$3" " $4" " $5" " $6" " $7" "$8" "$9" "$10" "$11" " $12$13$14$15$16$17$18$19$20$21$22$23$24$25$26$27$28$29$30$31$32$33$34$35$36$37$38$39$40$41$42$43$44$45$46$47}'>> apache_log.txt
下面就是要导入数据了。进入mysql的shell中
LOAD DATA INFILE "/data0/log.txt" INTO TABLE apache_log FIELDS TERMINATED BY " " LINES TERMINATED BY '\n';
#TERMINATED BY " "表示用空格区分分每项
#LINES TERMINATED BY '\n'表示用换行区分每列
经本人不厌其烦的测试。。解决掉遇到的几个问题。特此记录
1.一定要确认好表中的字段与经过awk处理好的每行中的项,看看是否对应。由于需求不一样,我这里数据表中要添加一个ID号,所以我要在日志中添加一个0
2.命令,处理日志的命令,如果大家觉得上面的awk写的比较雷人,可以用这个
awk '{print 0 " "$1 " "$2 " "$3" " $4" " $5" " $6" " $7" "$8" "$9" "$10" "$11" " for (i=12;i<=NF;i++) printf $i;printf "\n"}'
个人觉得还是第一种好点。速度快,但是它消耗更多的内存空间,事先就会把内存地址申请好,不管用不用到。而第二种就是动态的了。。哪个好,大家随意。我不是编程出身的。。小弟刚学shell。
3.load data infile 和load data local infile区别
在LOAD DATA LOCAL INFILE时报错:
ERROR 1148 (42000): The used command is not allowed with this MySQL version
原因一.编译时缺少参数。需要在编译时加上"--enable-local-infile"
原因二.
LOAD DATA INFILE 语句以非常高的速度从一个文本文件中读取记录行并插入到一个表中。如果 LOCAL 关键词被指定,文件从客户端主机读取。如果 LOCAL 没有被指定,文件必须位于服务器上。(LOCAL 在 MySQL 3.22.6 或更新的版本中被支持。)
由于安全性的原因,当读取位于服务器端的文本文件时,文件必须处于数据库目录或可被所有人读取的地方。同时,为了对服务器端的文件使用 LOAD DATA INFILE,你必须在服务器主机上有 FILE 权限。在 MySQL 3.23.49 和 MySQL 4.0.2 中,只有当你没有以 --local-infile=0 选项启动 mysqld,或你没有禁止你的客户端程序支持 LOCAL的情况下,LOCAL 才会工作。查看章节 4.2.4 LOAD DATA LOCAL 的安全性问题.
如果你指定关键词 LOW_PRIORITY,LOAD DATA 语句的执行将会被延迟,直到没有其它的客户端正在读取表。
如果你对一个 MyISAM 表指定关键词 CONCURRENT,那么当 LOAD DATA正在执行时,其它的线程仍可以从表中检索数据。使用这个选项时,如果同时也有其它的线程正在使用表,这当然会有一点影响 LOAD DATA 的执行性能。
使用 LOCAL 将比让服务器直接访问文件要慢一些,因为文件的内容必须从客户端主机传送到服务器主机。而在另一方面,你不再需要有 FILE 权限用于装载本地文件。
更多问题请参照手册吧。。祝你好运!