利用WEB服务器本身的多线程来处理,从WEB服务器多次调用我们需要实现多线程的程序。
PHP中也能多线程了,那么问题也来了,那就是同步的问题。
安徽电脑培训http://www.kmbdqn.cn/知道PHP本身是不支持多线程的,所以更不会有什么像Java中synchronize的方法了。
那我们该如何做呢?1.尽量不访问同一个资源。
以避免冲突。
但是可以同时像数据库 *** 作。
因为数据库是支持并发 *** 作的。
所以在多线程的PHP中不要向同一个文件中写入数据。
如果必须要写的话,用别的方法进行同步。
如调用flock对文件进行加锁等。
或建立临时文件,并在另外的线程中等待这个文件的消失while(file_exits('xxx'))这样就等于这个临时文件存在时,表示其实线程正在 *** 作。
如果没有了这个文件,说明其它线程已经释放了这个。
2.尽量不要从runThread在执行fputs后取这个socket中读取数据。
因为要实现多线程,需要的用非阻塞模式。
即在像fgets这样的函数时立即返回。
。
所以读写数据就会出问题。
如果使用阻塞模式的话,程序就不算是多线程了。
他要等上面的返回才执行下面的程序。
所以如果需要交换数据最后利用外面文件或数据中完成。
实在想要的话就用socket_set_nonblock($fp)来实现。
说了这么多,倒底这个有没有实际的意义呢?在什么时候需要这种用这种方法呢?答案是肯定的。
大家知道。
在一个不断读取网络资源的应用中,网络的速度是瓶颈。
如果采多这种形式就可以同时以多个线程对不同的页面进行读取。
我前几天有一个面试,面试题就是有这样一道题。先把自己的思路说一下,因为信息量非常的大,所以我采用了分表,分成24张表,每个小时一张,虽然凌晨时刻的表可能很少数据,但这样sum字段的问题就容易解决了,我理解的sum字段是一个小时同一个用户在相同的环境的登陆次数。这样理解不知对否,请网友自行甄辨。然后我通过PHP中的fgets函数一行一行的数据取出,入表。实验了几万条数据是没有问题的,但是上亿条数据可能够呛。这一点也请网友注意,我也是新手。只是看到这里没有答案,给大家一个参考。废话不多,看流程:
日志文件(access.log)格式:
200 /alipeng.gif?zoneid=2&bannerid=44&clentid=6&materialid=64&redirect=http%3a%2f%2fwww.alipeng.cn&time=1384444800.832&ip=127.0.0.1&user_agent=Mozilla/5.0 (X11 Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.48 Safari/537.36&utrace=a6dbdd2f6a37b946165b7ae98dcd4f79502 /alipeng.gif?zoneid=2&bannerid=44&clentid=6&materialid=64&redirect=http%3a%2f%2fwww.alipeng.org&time=1384444800.904&ip=127.0.0.1&user_agent=Mozilla/5.0 (X11 Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.48 Safari/537.36&utrace=a6dbdd2f6a37b946165b7ae98dcd4f79
配置文件cfg.php:
define(HOST,'localhost')//主机名define(USER,'root')//数据库账号
define(PASS,'111111')//数据库密码
define(DBNAME,'test')//所用的数据库
define(CHARSET,'utf8')//使用的字符集
具体代码test.php:
<?phpheader("content-type:text/htmlcharset=utf-8")
require './cfg.php'
$link = mysql_connect(HOST,USER,PASS) or die('连接数据库失败')
//程序中自动建库和建表,这样一定程度上拖慢了程序的速度
//创建数据库
$crdb="create database if not exists ".DBNAME
if(!mysql_query($crdb)){
die('创建数据库失败')
}
//链接数据库
mysql_select_db(DBNAME) or die('选择数据库失败')
mysql_set_charset(CHARSET)
//因为数据量很大我将数据按小时分表,分成24个表,每小时一个表,这样num字段的值也好做统计
//数据循环建表
for($i=0$i<24$i++){
if($i<10){
$tbhz='0'.$i//如果前10张表,表后缀应该是00-09
}else{
$tbhz=$i
}
$ctbsql="create table if not exists logininfo_{$tbhz}(
id int not null auto_increment primary key,
zoneid int not null default 0,
bannerid int not null default 0,
clentid int not null default 0,
materialid int not null default 0,
redirect char(200) not null default '',
time char(16) not null default '',
user_agent char(200) not null default '',
utrace char(32) not null default '',
sum int not null default 0
)TYPE=MyISAM DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci"
mysql_query($ctbsql)
}
//打开文件
$file=fopen("./access.log",'r') or die("打开文件失败")
//对文件内容进行循环,直到文件末尾才停止
while (!feof($file)){
//每次读取一行
$line = fgets($file,1024)
//状态是200的进行写入数据库 *** 作
if(preg_match('/^200/',$line)){
$pinfo=parse_url($line)//url信息
$ext=$pinfo['query']//取得传递的各个参数
$parray=explode('&',$ext)//根据&分解为数组
//因为分解为数组后并不是要的值,所以要对值进行一次截取,将等号及等号左边的都去掉
foreach($parray as $val){
$narray[]=ltrim(strstr($val,'='),'=')
}
$narray[8]=rtrim($narray[8],'_')
//截取时间的秒数
$getmun=substr($parray[5],5,10)
$time=date('Y-m-d H',$getmun)//将秒数转化为时间类型。
//得到表后缀
$tbhz=date('H',$getmun)
$sql="insert into logininfo_{$tbhz} values(null,'{$narray[0]}','{$narray[1]}','{$narray[2]}','{$narray[3]}','{$narray[4]}','{$time}','{$narray[7]}','{$narray[8]}',0)"
//echo $sql
$res=mysql_query($sql)//执行插入
if(!$res || !mysql_affected_rows()>0){
die('写入数据库失败')
}
unset($narray)//循环一次将narray销毁,为下一次循环做准备
//var_dump(parse_url($line)['query'])
}
}
fclose($file)//关闭
//因为sum字段还是0,下面代码段需要处理sum字段的值
//24张表循环处理
for($i=0$i<24$i++){
if($i<10){
$tbhz='0'.$i//如果前10张表,表后缀应该是00-09
}else{
$tbhz=$i
}
//该sql语句是把同一个小时内,并且符合条件相等的登陆的总次数和需要的登陆信息查出,为下面修改sum做准备
$sql="SELECT COUNT('zoneid') AS sum,zoneid,bannerid,clentid,materialid,redirect,user_agent,utrace FROM logininfo_{$tbhz} GROUP BY zoneid,bannerid,clentid,materialid,redirect,user_agent,utrace"
//发送查询sql
$res=mysql_query($sql)
if($res && mysql_num_rows($res)>0){
while($row=mysql_fetch_assoc($res)){
//修改sum字段,即同一小时内的登陆次数
$upsql="update logininfo_{$tbhz} set sum='{$row['sum']}' where zoneid='{$row['zoneid']}' and bannerid='{$row['bannerid']}' and clentid='{$row['clentid']}' and materialid='{$row['materialid']}' and redirect='{$row['redirect']}' and user_agent='{$row['user_agent']}' and utrace='{$row['utrace']}'"
//发送修改sql,执行修改sum
$upres=mysql_query($upsql)
if(!$upres){
die('修改登陆sum失败')
}
}
}
}
echo '数据成功入表'
使用说明:
将配置文件cfg.php中的连接数据库账号、密码修改为自己本机的(默认新增的库名是test)
直接运行test1.php
在使用PhpMyAdmin的时候经常用到数据的导入和导出(Export/Import),但是在导入大数据的时候由于php上传文件的限制和脚本响应时间的限制,导致phpMyAdmin无法导入大数据。很多时候都是由于文件过大,从本地浏览上传导入,容易中断失败,有没有更好的方法呢?
方法:
在phpMyAdmin的目录下,找到根目录的config.inc.php文件,
打开config.inc.php文件,查找$cfg['UploadDir'],这个参数就是设定导入文件存放的目录,这里把值设定为:ImportSQLFile。
在phpMyAdmin目录下,建立以ImportSQLFile命名的文件夹,
把我们需要导入的数据文件,放到ImportSQLFile文件夹下面,非常简单,
登入phpMyAdmin,选择需要导入的数据,点击导航条上面的“导入”按钮,
选中“从网站服务器上传文件夹ImportSQLFile/中选择:”选项,并需要导入的数据文件,
最后点击“执行”,即可导入成功。
注意事项
如果在config.inc.php文件,没有找到$cfg['UploadDir'],可以自己在文件中添加上去即可。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)