无法在没有主键的情况下创建或更改 table - Laravel DigitalOcean 托管数据库
Unable to create or change a table without a primary key - Laravel DigitalOcean Managed Database
我刚刚使用(托管数据库)将我的应用程序部署到 DigitalOcean,调用 php artisan migrate
时出现以下错误
SQLSTATE[HY000]: General error: 3750 Unable to create or change a table without a primary key, when the system variable 'sql_require_primary_key' is set. Add a primary key to the table or unset this variable to avoid this message. Note that tables without a primary key can cause performance problems in row-based replication, so please consult your DBA before changing this setting. (SQL: create table `sessions` (`id` varchar(255) not null, `user_id` bigint unsigned null, `ip_address` varchar(45) null, `user_agent` text null, `payload` text not null, `last_activity` int not null) default character set utf8mb4 collate 'utf8mb4_unicode_ci')
当 mysql var sql_require_primary_key
设置为 true 时,Laravel 迁移似乎不起作用。
你有什么解决办法吗?
启用后,sql_require_primary_key
具有以下效果:
- 尝试创建没有主键的新 table 失败并出现错误。这包括 CREATE TABLE ... LIKE。它还包括 CREATE TABLE ... SELECT,除非 CREATE TABLE 部分包含主键定义。
- 尝试从现有 table 中删除主键失败并出现错误,但允许删除主键并在同一 ALTER TABLE 语句中添加主键。
即使 table 也包含 UNIQUE NOT NULL 索引,删除主键也会失败。
- 尝试导入没有主键的 table 失败并出现错误。
默认值为 OFF
,但在您的情况下,您需要从 ON
设置 OFF
根据 MySQL 文档,此系统变量的用途是
to avoid replication performance issues: "Enabling this variable helps avoid performance problems in row-based replication that can occur when tables have no primary key."
恕我直言,您的问题有两种可能的选择;
- 将主键添加到这个和迁移中的每个 table,包括临时的 table。这个更好,我认为这样做更方便,因为每个 table.
都有主键没有缺点
Whether statements that create new tables or alter the structure of existing tables enforce the requirement that tables have a primary key.
- 更改您的提供商,因为根据 here "We support only MySQL v8."
这里还有bug report
只需添加 set sql_require_primary_key = off
像这样
到您的 SQL 文件。
将此行添加到您的迁移文件中。
$table->增量('aid');
很遗憾,我们无法更改数字海洋 MySQL 数据库中的 sql_require_primary_key 值。相反,您可以通过添加 primary()
将 id 设置为主键
我试图通过使用 WordPress 安装中的 mysqldump 文件导入 DO Managed MySQL 来解决这个问题。我发现将它添加到文件顶部确实对我的导入有用。
SET @ORIG_SQL_REQUIRE_PRIMARY_KEY = @@SQL_REQUIRE_PRIMARY_KEY;
SET SQL_REQUIRE_PRIMARY_KEY = 0;
然后我使用 JetBrains DataGrip 进行了导入,并且没有出现错误。
在您的第一次迁移中添加:
\Illuminate\Support\Facades\DB::statement('SET SESSION sql_require_primary_key=0');
内部:Schema::create()
函数。
我通过工单联系了 DigitalOcean,询问他们是否想禁用该要求,他们在第二天就这样做了:)
所以你可以直接问他们
Thanks for getting in touch with us!
I understand you will like to disable the primary requirement on your managed database. The primary requirement for your managed database ****** has been disabled
定义了一个简洁的解决方案here。解决方案是添加监听器来迁移脚本,并在执行迁移之前和之后打开和关闭 sql_require_primary_key
。此解决方案解决了无法修改迁移脚本的问题,例如当它们来自库或 Voyager 等框架时。
<?php
namespace App\Providers;
use Illuminate\Database\Events\MigrationsStarted;
use Illuminate\Database\Events\MigrationsEnded;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider {
/**
* Register any application services.
*
* @return void
*/
public function register() {
// check this one here https://github.com/laravel/framework/issues/33238#issuecomment-897063577
Event::listen(MigrationsStarted::class, function (){
if (config('databases.allow_disabled_pk')) {
DB::statement('SET SESSION sql_require_primary_key=0');
}
});
Event::listen(MigrationsEnded::class, function (){
if (config('databases.allow_disabled_pk')) {
DB::statement('SET SESSION sql_require_primary_key=1');
}
});
}
// rest of the class
}
对于更大的 sql 文件,可以使用此命令(如果您的文件大小 <8GB,nano 编辑器可以在 1 周内打开,哈哈):
第一个:
sed -i '1i SET SQL_REQUIRE_PRIMARY_KEY = 0;' db.sql
第二个:
sed -i '1i SET @ORIG_SQL_REQUIRE_PRIMARY_KEY = @@SQL_REQUIRE_PRIMARY_KEY;' db.sql
从 2022 年 3 月开始,您现在可以通过向数字海洋 API 发出请求来配置您的 MYSQL 和其他数据库。
这是参考:https://docs.digitalocean.com/products/databases/mysql/#4-march-2022
解决问题的步骤:
步骤 - 1:创建 AUTH 令牌以访问数字海洋 APIs。 https://cloud.digitalocean.com/account/api/tokens
STEP - 2:通过使用您刚刚在上面生成的承载令牌向下面URL发送GET请求来获取数据库集群ID。
URL: https://api.digitalocean.com/v2/databases
步骤 - 3:使用 PATCH 请求以及承载令牌和有效负载点击下面的 URL。
URL: https://api.digitalocean.com/v2/databases/{YOUR_DATABASE_CLUSER_ID}/config
有效载荷:{“配置”:{“sql_require_primary_key”:假}}
就是这样。它运行完美。
更多信息,请参考API文档:
https://docs.digitalocean.com/products/databases/mysql/#latest-updates
我刚刚使用(托管数据库)将我的应用程序部署到 DigitalOcean,调用 php artisan migrate
SQLSTATE[HY000]: General error: 3750 Unable to create or change a table without a primary key, when the system variable 'sql_require_primary_key' is set. Add a primary key to the table or unset this variable to avoid this message. Note that tables without a primary key can cause performance problems in row-based replication, so please consult your DBA before changing this setting. (SQL: create table `sessions` (`id` varchar(255) not null, `user_id` bigint unsigned null, `ip_address` varchar(45) null, `user_agent` text null, `payload` text not null, `last_activity` int not null) default character set utf8mb4 collate 'utf8mb4_unicode_ci')
当 mysql var sql_require_primary_key
设置为 true 时,Laravel 迁移似乎不起作用。
你有什么解决办法吗?
启用后,sql_require_primary_key
具有以下效果:
- 尝试创建没有主键的新 table 失败并出现错误。这包括 CREATE TABLE ... LIKE。它还包括 CREATE TABLE ... SELECT,除非 CREATE TABLE 部分包含主键定义。
- 尝试从现有 table 中删除主键失败并出现错误,但允许删除主键并在同一 ALTER TABLE 语句中添加主键。
即使 table 也包含 UNIQUE NOT NULL 索引,删除主键也会失败。
- 尝试导入没有主键的 table 失败并出现错误。
默认值为 OFF
,但在您的情况下,您需要从 ON
OFF
根据 MySQL 文档,此系统变量的用途是
to avoid replication performance issues: "Enabling this variable helps avoid performance problems in row-based replication that can occur when tables have no primary key."
恕我直言,您的问题有两种可能的选择;
- 将主键添加到这个和迁移中的每个 table,包括临时的 table。这个更好,我认为这样做更方便,因为每个 table. 都有主键没有缺点
Whether statements that create new tables or alter the structure of existing tables enforce the requirement that tables have a primary key.
- 更改您的提供商,因为根据 here "We support only MySQL v8."
这里还有bug report
只需添加 set sql_require_primary_key = off
像这样
到您的 SQL 文件。
将此行添加到您的迁移文件中。 $table->增量('aid');
很遗憾,我们无法更改数字海洋 MySQL 数据库中的 sql_require_primary_key 值。相反,您可以通过添加 primary()
将 id 设置为主键我试图通过使用 WordPress 安装中的 mysqldump 文件导入 DO Managed MySQL 来解决这个问题。我发现将它添加到文件顶部确实对我的导入有用。
SET @ORIG_SQL_REQUIRE_PRIMARY_KEY = @@SQL_REQUIRE_PRIMARY_KEY;
SET SQL_REQUIRE_PRIMARY_KEY = 0;
然后我使用 JetBrains DataGrip 进行了导入,并且没有出现错误。
在您的第一次迁移中添加:
\Illuminate\Support\Facades\DB::statement('SET SESSION sql_require_primary_key=0');
内部:Schema::create()
函数。
我通过工单联系了 DigitalOcean,询问他们是否想禁用该要求,他们在第二天就这样做了:)
所以你可以直接问他们
Thanks for getting in touch with us! I understand you will like to disable the primary requirement on your managed database. The primary requirement for your managed database ****** has been disabled
定义了一个简洁的解决方案here。解决方案是添加监听器来迁移脚本,并在执行迁移之前和之后打开和关闭 sql_require_primary_key
。此解决方案解决了无法修改迁移脚本的问题,例如当它们来自库或 Voyager 等框架时。
<?php
namespace App\Providers;
use Illuminate\Database\Events\MigrationsStarted;
use Illuminate\Database\Events\MigrationsEnded;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider {
/**
* Register any application services.
*
* @return void
*/
public function register() {
// check this one here https://github.com/laravel/framework/issues/33238#issuecomment-897063577
Event::listen(MigrationsStarted::class, function (){
if (config('databases.allow_disabled_pk')) {
DB::statement('SET SESSION sql_require_primary_key=0');
}
});
Event::listen(MigrationsEnded::class, function (){
if (config('databases.allow_disabled_pk')) {
DB::statement('SET SESSION sql_require_primary_key=1');
}
});
}
// rest of the class
}
对于更大的 sql 文件,可以使用此命令(如果您的文件大小 <8GB,nano 编辑器可以在 1 周内打开,哈哈):
第一个:
sed -i '1i SET SQL_REQUIRE_PRIMARY_KEY = 0;' db.sql
第二个:
sed -i '1i SET @ORIG_SQL_REQUIRE_PRIMARY_KEY = @@SQL_REQUIRE_PRIMARY_KEY;' db.sql
从 2022 年 3 月开始,您现在可以通过向数字海洋 API 发出请求来配置您的 MYSQL 和其他数据库。 这是参考:https://docs.digitalocean.com/products/databases/mysql/#4-march-2022
解决问题的步骤:
步骤 - 1:创建 AUTH 令牌以访问数字海洋 APIs。 https://cloud.digitalocean.com/account/api/tokens
STEP - 2:通过使用您刚刚在上面生成的承载令牌向下面URL发送GET请求来获取数据库集群ID。
URL: https://api.digitalocean.com/v2/databases
步骤 - 3:使用 PATCH 请求以及承载令牌和有效负载点击下面的 URL。
URL: https://api.digitalocean.com/v2/databases/{YOUR_DATABASE_CLUSER_ID}/config
有效载荷:{“配置”:{“sql_require_primary_key”:假}}
就是这样。它运行完美。
更多信息,请参考API文档: https://docs.digitalocean.com/products/databases/mysql/#latest-updates