Submitted by chrishu on Sun, 03/15/2015 - 15:08

Still running on Drupal 8

Somewhat shocked to find that I have been running on Drupal 8 for well over 1.5 years now, not surprisingly the sense of urgency has kind of dropped off, but getting back into Drupal 8 again now. This site was originally based on Alpha 3  D8 and I even tried 'chasing head' for one iteratation, so it was alpha 3 with some crazy ass fixes.

Then I got a bit experimental, customised a couple of things etc. and fixed the brokeness that kept happening. Utimately as I focused on it again (whilst having experimented a little on dev site with Beta 3 in preparation for migration), I touched something and it went poof! I am somewhat used to the white screen of death on this site even the white screen of death that doesn't fix itself when you rollback the database, this time I didn't want to roll up my sleaves and attempt a fix, as far as I was concerned my site was the Norwegian Blue Parrot of Drupal installs.

Note: if working on a non-supported version of D8 kittens don't die if you hack core, in fact coping with Drupageddon etc. they are more likely to die if you don't.

Alpha to Beta problem, Mysql to the rescue

A quick assessment of options, I could look at the migration code already in D8 and attempt something but two things stopped me, firstly I have spent a lot of time working on D6 - D7 and D7 - D7 migrations recently and great though it is I am sick of it, secondly I needed something really quick, I had very little spare time over the next week, I slapped up a new site on a shiny new Ubuntu 14.04 VPS and posted a page to explain what was going on. 

More annoyingly for speed I need content to have the same node ids etc. not having any automated path functionality I had too many /node/{nid} urls already.

It turns out that the thing that has changed the least over the intervening time is the database structure (well there are some important differences but nothing that cannot be fixed on the fly). When I got some time a couple of beers and the following strategy:

  1. dump the orginal site from Mysql.
  2. prefix all the tables from the original alpha site with prefix (eg. in my case 'node' became 'rr_node'.
  3. load the alpha site tables into the beta site database (they are just ignored and do no harm).
  4. copy a dev version of the site and move the data from the alpha tables to the beta tables, making changes as needed.
  5. move the dev version to live.

It worked a charm (although at the point of writing this I still have to do the comments, I was just getting bored). A few hours effort in total to get the old content into the new site.  Nice to see that the database tables are pretty clean and fairly easy to interpret by eye if all else fails.

Some Mysql pointers

To replicate this approach you need to be able to fire up a Mysql client and be pretty comfortable looking around moving data around. A few things that may help follow.

You can wildcard show tables. show tables like '%node%';  will show you node related tables for example.

You can view the structure of a table with describe  eg. describe node;

Tables that have the same structure are very easy to populate INSERT INTO url_alias SELECT * FROM rr_url_alias; tables where the structure varies (missing fields, field in a different order etc.) require the fields and field order to be specified:

INSERT INTO node_field_revision (nid, vid, langcode, title, uid, status, 
  created, changed, promote, sticky, default_langcode) 
SELECT nid, vid, langcode, title, uid, status, created, 
  changed, promote, sticky, default_langcode from rr_node_field_revision;

Language codes have to match, my old database was full of 'und' the new one needed 'en'

Revisions are better flattened, a lot of the complication in folding the two structures together are around revisions, I did have revisions in my original alpha site (not because I needed them, just to kick the tyres). It was much easier to flatten the revisions, in simple tables just making vid = nid or revision_id = entity_id does the job BUT in tables like field tables where multiple revisions are tracked for the same entity you want to delete all the older revision and then keep the last one, matching the revision_id to entity_id as appropriate. Drupal then just sees the content as having one revision and the last change will match the state as the last revision you had previously.

Give me a shout if you need help

I appeciate all the above is a bit holistic, as I said it took a few hours and a couple of beers from start to finish and was fairly hacky (I was cooking a meal at the same time etc.) I had no time to compile a structured migration guide (which may be different for your particular version of the site anyway), if you are confident with Mysql then a content migration (included taxonomy terms, etc etc. ) is a very feasible way to get ancient D8 content into a new spanking new D8 Beta and I FEEL GOOD

Happy to chip in if anyone else needs a hand.

Looking forward to trying out themeing now I have an up to date Drupal 8. 


I finally sorted out the comments in the same manner, I recorded the steps taken and have pasted an example below, this would have be more complicated if I had not imported all the previous data with the same node ids. 

-- Had a lot spam comments to delete but shoved them in a new table so 
-- I can delete them from other places also
CREATE TABLE del_comment AS SELECT cid FROM rr_comment WHERE status = 0;
DELETE FROM rr_comment WHERE status = 0;

-- The comment table is much more concise now, 14 is because I already have some
-- comments in the new site.
INSERT INTO comment SELECT cid, 'comment', uuid, 'en' FROM rr_comment WHERE cid > 14;

-- Use that table I created to delete all the spam comment bodies
DELETE FROM rr_comment__comment_body WHERE entity_id IN (SELECT cid FROM del_comment);

INSERT INTO comment__comment_body SELECT * FROM rr_comment__comment_body WHERE entity_id > 14;

-- Comment field data is a new one I need to pull things in from a couple of places so easier
-- to build initially into a new table, this is an easy way to replicate the structure.
CREATE TABLE comment_field_data_shadow AS SELECT * FROM comment_field_data;
TRUNCATE comment_field_data_shadow;
INSERT INTO comment_field_data_shadow SELECT cid,'comment','en',pid,nid,subject,uid,name,mail,homepage,hostname,created,changed,status,thread,'node','comment','en' FROM rr_comment WHERE cid > 14;

-- Populate the real comment field FROM my constructed table.
INSERT INTO comment_field_data SELECT * FROM comment_field_data_shadow;

-- I was acting under a different user name on the old site.
UPDATE comment_field_data set uid = 1 WHERE uid = 2;

-- Now need to patch up a few diffences in the way the data was stored
UPDATE comment_field_data set pid = NULL WHERE pid = 0;
UPDATE comment_field_data set mail = NULL;
UPDATE comment_field_data set hostname = NULL;
UPDATE comment_field_data set default_langcode=1;

-- Finally update the comment statistics for nodes, not just for convenience
-- in particular if you don't do this anonymous cannot see the comments.
INSERT INTO comment_entity_statistics SELECT nid, 'node', 'comment', cid, last_comment_timestamp, last_comment_name, last_comment_uid, comment_count FROM rr_node_comment_statistics WHERE nid > 1;

-- Some comments I made as a user that does not exist on this site.
UPDATE comment_entity_statistics set last_comment_uid = 1 WHERE last_comment_uid = 2;


Mon, 03/16/2015 - 11:22

In reply to by Anonymous (not verified)

That is interesting, I hadn't seen this project, seems like there should have been a version for D8 though, I will have a quick look at what it was doing. 

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.