Laravel在Docker搭配MariaDB10.6执行alter table迁移报连接拒绝错误
问题成因
- MariaDB 10.6 新增的原子DDL特性和Laravel默认开启的PDO持久化连接存在兼容性冲突,这是问题的核心原因:
- Laravel 执行上述
Schema::create闭包时会拆分两次SQL请求:首先执行CREATE TABLE创建表结构,再单独执行ALTER TABLE添加联合唯一索引 - MariaDB 10.6默认开启原子DDL,执行完DDL操作后会主动断开当前持有的非交互式持久化PDO连接,Laravel执行第二步加索引操作时复用已被断开的连接,就会抛出
Connection refused报错 - 手动执行SQL时使用的是交互式连接,不会被服务端主动断开,因此可以正常执行
- Laravel 执行上述
- MariaDB 10.5及更早版本不支持原子DDL,执行DDL后不会主动断开持久化连接,因此迁移可正常运行。
- 附加触发条件:Laravel数据库配置默认开启PDO持久化连接,同时MariaDB 10.6的
wait_timeout默认值相比10.5有所下调,进一步提升了问题触发概率。
解决方案
按优先级从高到低可选择以下任意一种方案:
方案1:关闭PDO持久化连接(最稳妥,无副作用)
修改config/database.php中mysql连接的options配置,关闭持久化连接:
'mysql' => [ // 原有配置项保持不变 'options' => [ PDO::ATTR_PERSISTENT => false, // 其他原有option配置保留即可 ], ],
修改后执行php artisan config:clear清除配置缓存,再重新运行迁移即可正常执行。
方案2:调整MariaDB配置适配现有连接逻辑
修改MariaDB 10.6的配置文件(Docker环境通常挂载的my.cnf),添加以下参数:
# 关闭原子DDL特性 atomic_ddl=OFF # 延长非交互式连接超时时间 wait_timeout=600 interactive_timeout=600
重启MariaDB容器后重新运行迁移即可。
方案3:拆分迁移的DDL操作
将原迁移文件拆分为两个独立迁移,分别执行建表和加索引操作,避免同一个连接内连续执行两次DDL:
第一步迁移(仅建表):
Schema::create('team_invitations', function (Blueprint $table) { $table->id(); $table->foreignId('team_id')->constrained()->cascadeOnDelete(); $table->string('email'); $table->string('role')->nullable(); $table->timestamps(); });
第二步迁移(单独加索引):
Schema::table('team_invitations', function (Blueprint $table) { $table->unique(['team_id', 'email']); });
内容的提问来源于stack exchange,提问作者anotherOneHere
相关产品推荐
相关产品推荐

