当使用 Monolog 时StreamHandler
,这是正常情况,PHP 脚本的多个实例会并行写入同一个日志文件。
(例如,在我的 Symfony 应用程序中,当多个用户同时打开“登录页面”时,会导致我的应用程序脚本出现多个实例(app.php
)运行,因此 Monolog 的两个实例StreamHandler
将写入相同的app/logs/prod.log
.)
为什么尽管并发写入文件,但每个日志行都没有在中间中断和混乱?为什么下面的情况从来没有发生过:
-
实例1StreamHanler 只写了一半的日志行,
-
实例2StreamHandler 写它的前半部分
-
实例1写了日志行的后半部分
-
实例2写了日志行的后半部分
- 现在我们的日志文件一团糟,因为两行是混合的。
我尝试查看源代码StreamHanler
https://github.com/Seldaek/monolog/blob/master/src/Monolog/Handler/StreamHandler.php#L93 https://github.com/Seldaek/monolog/blob/master/src/Monolog/Handler/StreamHandler.php#L93
但我没有看到任何适当的并发控制,有一个flock()
但它似乎被禁用了(->useLocking=false
)在默认(Symfony)配置中,似乎日志没有它就很好......
if ($this->useLocking) {
// ignoring errors here, there's not much we can do about them
flock($this->stream, LOCK_EX);
}
fwrite($this->stream, (string) $record['formatted']);
if ($this->useLocking) {
flock($this->stream, LOCK_UN);
}
但为什么日志却神奇地完好呢?
当我使用日志记录时,我希望底层组件能够正常工作。它不是您必须确保并发访问的任何容器。
我读过,主流操作系统使用线程安全的 io 调用,这些调用也是不可中断的,并且存在非线程安全调用。
您可以在这里阅读,但在我看来,标记的答案根本不正确:fwrite 是原子的吗? https://stackoverflow.com/questions/2220525/is-fwrite-atomic
换句话说,我从来没有遇到过任何破损的木头。就像是INSERT
在数据库中。要么插入一行,要么没有插入行。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)