Rails 5.2.1+Apartment生产环境Tenant Not Found问题求助
看起来你遇到的核心问题是:Apartment没有正确使用你在tenant_names哈希里指定的预定义数据库名(比如usr_webxx_2),反而尝试连接与租户名同名的数据库(tenant_one),导致权限错误。下面是一步步的排查和解决思路:
1. 强制关闭Schema模式(关键配置)
首先确认use_schemas必须设置为false——因为你采用的是每个租户独立数据库的模式,而非PostgreSQL的Schema共享数据库模式。即使你之前尝试过这个设置,也要确保配置位置正确:
在config/initializers/apartment.rb中添加:
config.use_schemas = false
当use_schemas为true时,Apartment会优先尝试Schema切换逻辑,直接忽略你在tenant_names里的数据库配置,这很可能是问题根源。
2. 验证tenant_names配置是否生效
登录生产环境的Rails控制台,执行以下命令确认配置是否正确加载:
puts Apartment.tenant_names.inspect
预期输出应该是你定义的哈希:
{"tenant_one"=>{:adapter=>"mysql2", ..., :database=>"usr_webxx_2"}, "tenant_two"=>{...}}
如果输出不是这个(比如是lambda或者空值),说明你的环境判断逻辑有问题——检查Rails.env.production?是否在生产环境中正确返回true(有些托管商会设置特殊的环境变量,比如RAILS_ENV=production是否正确配置)。
3. 手动测试租户切换逻辑
在生产控制台中手动切换租户,验证数据库连接是否正确:
Apartment::Tenant.switch('tenant_one') do puts "当前连接的数据库:#{ActiveRecord::Base.connection.current_database}" end
如果输出的是tenant_one而非usr_webxx_2,说明Apartment没有读取到你的哈希配置。这时候可以尝试:
- 升级Apartment到适配Rails 5.2.1的稳定版本(比如2.x系列,旧版本可能存在哈希配置解析的bug)
- 显式指定数据库管理器,在
apartment.rb中添加:config.database_manager = Apartment::Database::Mysql2Manager
4. 检查数据库用户权限
虽然你提到迁移已完成,但要确认webxx用户确实拥有访问usr_webxx_2和usr_webxx_3的权限。可以通过MySQL命令行验证:
mysql -u webxx -p # 登录后执行 SHOW GRANTS FOR 'webxx'@'localhost';
确保输出中包含GRANT ALL PRIVILEGES ON usr_webxx_2.* TO 'webxx'@'localhost';这类权限语句。
5. 验证中间件顺序
Apartment的子域名电梯中间件需要在正确的位置运行,避免被其他中间件干扰。在生产环境执行:
rake middleware
确保Apartment::Elevators::Subdomain出现在ActionDispatch::Routing::RouteSet之前,且在ActionDispatch::Cookies、ActionDispatch::Session::CookieStore等会话相关中间件之后。
6. 排查配置加载顺序
如果以上都没问题,检查是否有其他初始化代码覆盖了tenant_names配置。比如是否有其他initializer文件在apartment.rb之后加载,修改了Apartment.config.tenant_names。
内容的提问来源于stack exchange,提问作者M. Kreisler

