PHP 会话写入是原子的吗?

Are PHP session writes atomic?

由于 PHP 会话处理程序在过去存在某种缺陷,我们几年前开发了一个自制的会话处理程序。 但是 PHP 的当前版本似乎已经开发得很好并且缺陷已经消失,我们决定使用 PHP 的默认会话处理程序(因为它比我们使用 dbms 保存会话的处理程序快得多数据 - 有时需要 read/write 兆字节的数据)。

我们唯一找不到答案的问题是 PHP 的默认会话处理程序是否是原子的?

我们知道会话文件被锁定,因此很容易出现竞争条件,但是原子性呢?如果要将数兆字节的数据保存在会话文件中,并且在中间发生一些错误(例如断电、崩溃或磁盘故障)怎么办?现在发生了什么?会话数据现在损坏了吗?还是旧数据还在?

我们团队中没有 C 程序员,但我查看了 PHP 的源代码,找到了负责将会话写入文件的行,但我找不到s_write()的源代码文件。

ret = PS(mod)->s_write(&PS(mod_data), PS(id), val, PS(gc_maxlifetime));

这是源文件(第 487 行): https://github.com/php/php-src/blob/master/ext/session/session.c

在对源代码进行一些挖掘之后,我找到了 function that writes the data to the disk

3个函数可以被ps_files_write用来写入数据:

  • _write,Win32
  • prwite,好像是UNIX的一个函数,说实话我不太了解
  • write,基本的C系统调用。

根据上面的链接,所有这些都是“原子的”,因为如果遇到错误(磁盘空间不足 space、未经授权的访问、锁定的文件),它们不会刷新写入缓冲区等)。

ps_files_write returns 一个状态值(SUCCESSFAILURE),稍后在 php_session_save_current_state 到 return ERROR 到 PHP 脚本。

所以是的,通常你可以认为会话写入是“原子的”,即使在某些情况下你无法保证(如果突然断电,系统会在微秒内停止​​,所以什么都不能得救...)。