Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel - seeding large SQL file

A memory exhaustion happens when I run my DB seed script in production.

Below is my seed script.

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"));
    }
}

So what I did was add a no-limit on my seed script.

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

The problem now is that when I run the script it logs the output into the terminal the content of the SQL script (which is very, very big).

Is there a good way of running a SQL dump inside my DB seeds that doesn't consume much memory? What I did now was run it manually:

mysql -uuser -p db < script.sql
like image 333
olleh Avatar asked Sep 18 '14 06:09

olleh


2 Answers

For others who prefer a more Laravel-ish solution, this is how I handled it:

/**
 * 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);
        }
    }
}
like image 68
winkbrace Avatar answered Sep 30 '22 07:09

winkbrace


The problem happens because when using Db::unprepared it also logs the query to the laravel.log file, making in background much more actions then you think, from this side you have memory exhaust. If you are not running the safe mode I would stick to executing the console command like this:

exec("mysql -u ".\Config::get('database.mysql.user')." -p".\Config::get('database.mysql.password')." ".\Config::get('database.mysql.database')." < script.sql")
like image 36
Vit Kos Avatar answered Sep 30 '22 05:09

Vit Kos