11

当我在生产中运行我的数据库种子脚本时,会发生内存耗尽。

下面是我的种子脚本。

class MembershipTableSeeder extends Seeder 
{
    public function run()
    {
        DB::table('members')->delete();

        foreach (range(1, 99) as $days){
            Members::create(array('membership_code' => 'test'.$days));
        }

        DB::unprepared(file_get_contents(app_path()."/database/seeds/members.sql"));
    }
}

所以我所做的是在我的种子脚本上添加一个无限制的。

ini_set('memory_limit', '-1');

现在的问题是,当我运行脚本时,它会将 SQL 脚本的内容(非常非常大)记录到终端中。

有没有一种在我的数据库种子中运行 SQL 转储而不消耗太多内存的好方法?我现在做的是手动运行它:

mysql -uuser -p db < script.sql
4

4 回答 4

15

对于其他更喜欢 Laravel-ish 解决方案的人,我是这样处理的:

/**
 * This class is responsible for running the data dump sql.
 * It is recommended to update this class instead of creating new ones for new database content dumps.
 */
class DatabaseDumpSeeder extends Seeder
{
    /**
     * Run the database seeds.
     * @throws \Exception
     */
    public function run()
    {
        // Note: these dump files must be generated with DELETE (or TRUNCATE) + INSERT statements
        $sql = file_get_contents(__DIR__ . '/dumps/dump-20150709.sql');

        if (! str_contains($sql, ['DELETE', 'TRUNCATE'])) {
            throw new Exception('Invalid sql file. This will not empty the tables first.');
        }

        // split the statements, so DB::statement can execute them.
        $statements = array_filter(array_map('trim', explode(';', $sql)));

        foreach ($statements as $stmt) {
            DB::statement($stmt);
        }
    }
}
于 2015-07-09T13:54:17.473 回答
12

之所以会出现问题,是因为在使用 Db::unprepared 时,它还会将查询记录到 laravel.log 文件中,在后台进行的操作比您想象的要多得多,从这方面来看,您会耗尽内存。如果您没有运行安全模式,我会坚持执行控制台命令,如下所示:

exec("mysql -u ".\Config::get('database.mysql.user')." -p".\Config::get('database.mysql.password')." ".\Config::get('database.mysql.database')." < script.sql")
于 2014-09-18T07:55:51.650 回答
2

在 Project_directory/database/seeds 中创建种子文件“PostalCodeTableSeeder.php”

使用 Illuminate\Database\Seeder;

类 PostalCodeTableSeeder 扩展播种机 {
    /**
     * 运行数据库种子。
     *
     * @return 无效
     */
    公共函数运行()
    {
        // ================================================= ==============
        // 文件路径 -> Project/app/configs/database.php
        // 获取数据库名称、数据库用户名、数据库密码
        // ================================================= ==============
        $db = \Config::get('database.connections.mysql.database');
        $user = \Config::get('database.connections.mysql.username');
        $pass = \Config::get('database.connections.mysql.password');

        // $this->command->info($db);
        // $this->command->info($user);
        // $this->command->info($pass);

        // 在 php 代码中运行命令行导入
        exec("mysql -u".$user."-p".$pass."".$db."<postal_codes.sql");
        // postal_codes.sql 在根文件夹中
    }
}

还将类名添加到 Project_directory/database/seed/DatabaseSeeder.php 中,如下面的代码

使用 Illuminate\Database\Seeder;

类 DatabaseSeeder 扩展 Seeder
{
    /**
     * 运行数据库种子。
     *
     * @return 无效
     */
    公共函数运行()
    {
        $this->call(PostalCodeTableSeeder::class);
        // $this->call(UsersTableSeeder::class);
    }
}
于 2016-09-23T04:34:41.707 回答
0

我遇到了一个奇怪的问题,将大型 SQL 文件作为迁移导入会导致该行未添加到迁移表中。

这就是我修复它的方法。

$path = 'database/data.sql';
$command =  "mysql -h".env('DB_HOST')." -u".env('DB_USERNAME')." ".(env('DB_PASSWORD')?"-p'".env('DB_PASSWORD')."'":'')." ".env('DB_DATABASE')." < ".$path;
exec($command);

我注意到对此有类似的答案,但我的方法检查 .env 而不是应用程序配置,支持远程 MySQL 主机,也适用于本地没有密码和带有特殊字符的密码会破坏命令行。

于 2021-11-21T18:40:15.007 回答