分享一下经验,容易被忽视的session_commit

蓝色_冰点 2011-09-15 11:50:14
这段时间一直在用PHP做报表,碰到了一些非常头痛的问题,就是有些报表的SQL跑的时间比较长,而当这个报表正没有结束运行的时候,其它的报表页面就绝对被卡住
经过一步步分析,终于找到了病症之处:session
session最常用的就是记录用户的登陆信息,而在不少资料中,会告诉你,session_start()后,无需自己去调用session_commit(),脚本在结束后自动调用session_commit()
如果你的脚本运行的时间很短,自然不会出什么问题,但如果是需要比较长的运行时间的话,就杯具了。。。。
看看下面这两个简单的脚本吧,拿去运行一次,你就知道什么结果了
test.php
<html>
<head>
<title></title>
</head>
<body>
<?php
session_start();
$_SESSION["message"]="我留下的脚印";
// session_commit();
sleep(20);
?>
休息了20秒钟...
</body>
</html>


test2.php
<html>
<head>
<title></title>
</head>
<body>
<?php
session_start();
//session_commit(); //别担心,session_commit()以后,$_SESSION数组的内容还在.
echo $_SESSION["message"]."<br/>";
?>
我等到花儿也谢了
</body>
</html>

先运行test.php,然后20秒之内运行test2.php。按道理,test2.php会一下子就闪出来,但因为test.php还在抓住session不放,于是test2.php就被session_start()卡住了,直到test.php结束后,test2.php才得以继续。
而如果把代码中注释掉的那两行加上的话,才会得到我们所期望的效果。
我被这个小问题困扰了好一阵子,在这里分享一下经验给各位新手们:记住及时的session_commit(),别听那些只会copy的人在那说不用手动调用session_commit(),否则吃苦的就是你
...全文
1244 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
黄袍披身 2011-09-15
  • 打赏
  • 举报
回复
thx.这么看来SESSION 在写数据结束的时候 还是顺带的给 write_close比较合适

Description:
————
Calling session_start() appears to wait until other scripts have exited
that are using the same session. My guess is the 1st request locks the
session file for exclusive use, and the second request blocks until it
can open it.



Thank you for taking the time to write to us, but this is not a bug.This is expected, the session file is locked to avoid corruption.
蓝色_冰点 2011-09-15
  • 打赏
  • 举报
回复
session_commit()也就是session_write_close()会把$_SESSION数组的内容写入到服务器上的文件中,但不会清空$_SESSION的变量内容
session_start()则是打开那个文件,并随时准备写内容
黄袍披身 2011-09-15
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 sharp_ice 的回复:]

呃。。。估计是你没关掉浏览器窗口,所以传过去的应该是上上上几次留下的脚印吧
[/Quote]

是.忘记了。那么除了 session_commit 看样子就只有不使用session 或者在 运行代码之后再 session了.
这个 session_commit 难道不会影响session?
蓝色_冰点 2011-09-15
  • 打赏
  • 举报
回复
呃。。。估计是你没关掉浏览器窗口,所以传过去的应该是上上上几次留下的脚印吧
黄袍披身 2011-09-15
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 sharp_ice 的回复:]

报表SQL,有时统计大数据量的报表的时候,需要运行很长的时间
<?php

sleep(20);
session_start();
$_SESSION["message"]="我留下的脚印";
?>
你的这改法,很容易理解,前20秒时间内,因为还没有执行session_start(),所以session文件没有被打开
所以test2.php可以很快就打开
[/Quote]

问题是 $_SESSION["message"]="我留下的脚印"; 这个也传递过去了 就在前20秒
蓝色_冰点 2011-09-15
  • 打赏
  • 举报
回复
报表SQL,有时统计大数据量的报表的时候,需要运行很长的时间
<?php

sleep(20);
session_start();
$_SESSION["message"]="我留下的脚印";
?>
你的这改法,很容易理解,前20秒时间内,因为还没有执行session_start(),所以session文件没有被打开
所以test2.php可以很快就打开
黄袍披身 2011-09-15
  • 打赏
  • 举报
回复
嗯 翻了一下手册,这个session 的确是 “单线程"的为了防止并发的写入,必须只有一个脚本在操作.所以其实session换成其他只允许单个执行的函数在sleep下也会出现这样的情况。
该纠结的是 什么东西要运行这么久?大型计算?那是不是不应该采用session更合适些。

更搞的是当我把你的第一个页面修改成

<?php

sleep(20);
session_start();
$_SESSION["message"]="我留下的脚印";
?>
休息了20秒钟...

的时候 问题就解决了... 呵呵
蓝色_冰点 2011-09-15
  • 打赏
  • 举报
回复
这是 session_commit() 的说明,也就是session_write_close()

void session_write_close ( void )
End the current session and store session data.

Session data is usually stored after your script terminated without the need to call session_write_close(), but as session data is locked to prevent concurrent writes only one script may operate on a session at any time. When using framesets together with sessions you will experience the frames loading one by one due to this locking. You can reduce the time needed to load all the frames by ending the session as soon as all changes to session variables are done.

我用红色显示的地方,意思就是任何时候只有一个脚本文件可以操作session文件
所以如果不及时session_commit(),而且脚本运行时间过长的话,肯定会影响其它页面对session的读取
黄袍披身 2011-09-15
  • 打赏
  • 举报
回复
我认为不是 session的问题,而是 sleep的问题...
「已注销」 2011-09-15
  • 打赏
  • 举报
回复
谢谢 呵呵
craboy1 2011-09-15
  • 打赏
  • 举报
回复
受教!可能和服务器配置也有关系。

21,895

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧