下面的这段错误就是因为不知道为何连接到了A数据库而出现的:
分析过程
第一个猜想到的是不是在B应用连接数据库时,直接使用的是A应用中连接数据库的的资源ID,但是感觉这种情况应该不会出现。
另外一种情况,就是读取数据库配置的时候出错了,读取到了A应用的数据库配置信息,但是这个感觉理论有点不太可能,因为两个应用完全在两个不同的位置(后来证实确实是第二点)。
Laravel使用了 vlucas/phpdotenv
这个包来加载 .env
文件中的配置信息,具体的过程如下:
- 从
.env
文件中读取配置信息; - 调用
putenv()
方法将配置信息设置到PHP环境中; - 调用 Laravel 封装的
env()
方法来读取配置信息(env()
中其实调用了getenv()
方法来配置信息读取);
.env
文件主要功能是为了在不同的部署环境实现不同配置,这样不同的环境可以共用同一套代码;putenv()
和getenv()
是PHP4,PHP5,PHP7支持的用来设置和获取环境变量(environment variable)的方法。
问题就出现在这里。
getenv()
和 putenv()
不是一个线程安全的函数,意味着如果两个线程同时调用这个函数,就会出现问题。
而且服务器的环境正好是:
Apache + worker 模式,这种模式下,php运行环境是以线程模式运行的,所以才出现了上述的问题。
解决办法
- 启用php进程运行模式(参照
articles/dev/server/run_environments_for_php.md
); - 将配置单独放在php配置文件中,这个可能造成硬编码,不过不推荐;
- 等待Laravel修复这个问题。