Vil*_*lx- 10 php mysql session persistence
我正在尝试在PHP + MySQL中实现自定义会话持久化.大多数东西都是微不足道的 - 创建你的数据库表,创建你的读/写函数,调用session_set_save_hander()等等.甚至有几个教程为你提供了示例实现.但不知何故,所有这些教程都方便地忽略了一个关于会话持久性的微小细节 - 锁定.现在,真正的乐趣开始了!
我看了一下PHP 的session_mysql PECL扩展的实现.这使用MySQL的功能get_lock()和release_lock().看起来不错,但我不喜欢它的做法.锁定在读取功能中获取,并在写入功能中释放.但是如果写函数永远不会被调用怎么办?如果脚本以某种方式崩溃,但MySQL连接保持打开(由于池或其他东西)怎么办?或者如果脚本进入致命的僵局怎么办?
我刚遇到一个问题,一个脚本打开一个会话,然后尝试flock()通过NFS共享一个文件,而另一个计算机(托管该文件)也做同样的事情.结果是flock()-over-NFS调用在每次调用时阻止脚本大约30秒.它是在20次迭代的循环中!由于这是一个外部操作,PHP的脚本超时不适用,并且每次访问此脚本时会话都被锁定超过10分钟.而且,幸运的是,这是每5秒钟由AJAX shoutbox进行轮询的脚本......主要的showstopper.
我已经对如何以更好的方式实现它有一些想法,但我真的想听听其他人的建议.我没有那么多使用PHP的经验来了解哪些细微的边缘情况在阴影中隐约可能有一天会危及整个事物.
添加:
好吧,似乎没有人有任何建议.那么,这是我的想法.我想对这可能出错的地方提出一些意见.
INSERT IGNORE INTO sessions (id, data, lastaccesstime, locktime, lockid) values ($sessid, null, now(), null, null);- 这将创建会话行(如果它不存在),但如果它已经存在则不执行任何操作;UPDATE sessions SET (lastaccesstime, locktime, lockid) values (now(), now(), $guid) where id=$sessid and (lockid is null or locktime < date_add(now(), INTERVAL -30 seconds));- 这是一个原子操作,它将获得会话行的锁定(如果它没有锁定或锁定已过期),或者什么都不做.mysql_affected_rows()是否已获得锁定.如果获得 - 继续.如果不是 - 每0.5秒重新尝试一次操作.如果在40秒内仍未获得锁定,则抛出异常.UPDATE sessions SET (lastaccesstime, data, locktime, lockid) values (now(), $data, null, null) where id=$sessid and lockid=$guid;这是另一个原子操作,它将使用新数据更新会话行,如果仍有锁定则删除锁定,但如果锁定已被删除则不执行任何操作.gc被请求的操作,简单地删除所有行lastaccesstime太旧了.有人能看到这个漏洞吗?
| 归档时间: |
|
| 查看次数: |
4545 次 |
| 最近记录: |