delete

convert legacy django mysql dbs from myisam to innodb

The Problem and the Virtue of Transactions

Disclaimer: a long time programmer, old guy, learning new tricks. If I made a mistake please let me know in the comments and I’ll credit and update the post. Thanks!

Short version: For Django – MYISAM BAD. INNODB GOOD. Fight it if you wish, but for me, this was the bug and the fix. (Oh, and everything below relates to a Mac OS X 10.7.3 so translate to your OS.)

Django supports transactions. This is a good thing. And recommended. In my case I had a bug where something in admin delete worked on my local machine but did NOT work in staging. Tres embarrassant!

Specifically (for the now open source Tendenci software) I was struggling with building a Tendenci Django plugin with related objects (categories, etc) and attached images (files). Basic CRUD stuff. CRUD worked on my django dev environment locally, but only CRU worked and D failed in staging. Specifically Django failed on delete with a relationship error. Can’t delete three things at once. Why? Hmmmm. Stumped.

Thanks to debugging by JMO, he found the difference is our staging and production database servers have tables that are set to INNODB as the storage engine and my local mySQL defaulted database tables to MYISAM (MySQL 5.1). Thus trying to delete an object through the Django admin failed in staging because it could not delete three things at once in INNODB which strictly enforces relationship rules. OK, that seems fair. MYISAM is more willy-nilly-do-whatever. Which means you have scraps of relational data left in your tables. Yuck. Long-term-data-mining-hell.

Bottom line – transactions in Django are not supported at a database level with Django middleware with MYISAM and thus I couldn’t wrap a (multi-)delete into one call in admin.py. Sure we could programmatically delete the objects in sequence as a quick bug fix, Yet I’d rather let Django handle the heavy lifting (and shorter code). And long term there is a strong need for transactions. Especially in the age of RESTFUL APIs (I miss you soap! NOT!) In current web development with API calls dependencies can easily be on 30 routers and 20 servers just so you can post a pic of your chicks to Instagram Flickr. Thus you have to be able to roll back transactions. That is part of what a framework does. And transaction rollbacks clearly should NOT be the application layer’s job IMHO. MVC and all even if C is in V in Django. Another debate…. So transactions it is.

How to upgrade the dev mysql database environment from MYISAM to INNODB?

The fix that worked for me came from this post on converting a mysql database to INNODB for Drupal as well as several others credited below. While this post is on Django, Drupal still supports both MYISAM and INNODB, the default in Drupal 7 is now INNODB. So don’t fight the man. I’m moving to INNODB for Django too.

What steps are required for Django on MYISAM on a Mac OSX to get transactions working in Django? Combining a few of the posts (all linked below) and the django transactions help file you wind up with the following:

First convert your database. To do this create a temp directory and change (cd temp) into it using terminal. Run the commands from this post. I repeated them below slightly changed and I am skipping the prompt indicator to make it easier to copy.

First check if this is even a problem by getting a list of databases that have tables that use MYISAM

mysql -u USERNAME -p
#it will prompt for your password here
SELECT table_schema, table_name FROM INFORMATION_SCHEMA.TABLES WHERE engine = 'myisam';

You will get some results from “information_schema” and “mysql” and I’d recommend not changing those. Just look for your dev databases.

Second create the SQL file to change the offending databases that are your Django mysql databases.

cd temp
mysql -u USERNAME -p -e "SHOW TABLES IN YOURDATABASENAME;" | tail -n +2 | xargs -I '{}' echo "ALTER TABLE {} ENGINE=INNODB;" > alter_table.sql

It will prompt you for your password and replace the USERNAME and the YOURDATABASENAME with your own. Side note, don’t put a dash in your database name or it won’t work. I want those 30 minutes of my life back. Moving on….

I’m a curious guy so I wanted to see the contents of the sql file. (Replace “Sublime Text 2″ with the text editor of your choice. I just use Sublime because Glen told me to).

open -a "Sublime Text 2" alter_table.sql

Ooooh. Aaaaah. Looks fine. OK, close that. From there I prefer to do the update one database at a time to be sure so this:

mysql -u USERNAME -p YOURDATABASENAME < alter_table.sql

Then to confirm run the myisam table query again (which we hope does NOT show our now converted DB.)

SELECT table_schema, table_name FROM INFORMATION_SCHEMA.TABLES WHERE engine = 'myisam';

All good? Cool.

For all I know INNODB might break another database so I am only focusing on your Django mysql databases. Now in your settings.py file in your Django project be sure you have the following line as part of your DATABASES setting.

'OPTIONS': {"init_command": "SET storage_engine=INNODB",}

The whole settings.py mysql connection setup now looks like this because I hate when people leave off the context of where to put code or the details (I’m looking at you StackOverFlow.) /rant/Actually the only thing I hate more are code examples that use sqllite because they are close to useless. /rant/

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'YOURDATABASENAME',
        'USER': 'USERNAME',
        'PASSWORD': 'BLAH',
        'HOST': 'BLAH',
        'PORT': 'BLAH',
        'OPTIONS': {"init_command": "SET storage_engine=INNODB",}
    }
}

Now when you run from your project directory the usual “python manage.py syncdb“ command it doesn’t use the database defaults regardless. Anything new should be automatically created INNODB.

The following posts are the entire basis of the content above. I just combined it all in one place specific to Django and MySQL on Mac OS X. Comments and corrections are welcome.

  1. https://docs.djangoproject.com/en/dev/topics/db/transactions/
  2. http://djangosaur.tumblr.com/post/357759467/django-transaction-mysql-engine-innodb
  3. http://www.electrictoolbox.com/find-innodb-tables-mysql/
  4. http://www.mikebernat.com/blog/MySQL_-_InnoDB_vs_MyISAM
  5. http://highervisibilitywebsites.com/convert-your-mysql-database-myisam-innodb-and-get-ready-drupal-7-same-time
  6. http://stackoverflow.com/questions/9947671/performance-difference-between-innodb-and-myisam-in-mysql
  7. http://tag1consulting.com/MySQL_Engines_MyISAM_vs_InnoDB

 

delete

mind as water as programming

There is a natural conflict between youth and programming. Frequently the best programming ideas, like in mathematics or chess, come from young people. Sometimes under 30. And in my experience focus becomes harder as you age. Young people don’t know what they can’t do and this often allows them hit the ball out of the park! A very good thing indeed!

The contradiction is the young guns with the fresh mental horsepower have the least experience and frequently charge around randomly between the latest cool “philosophy” and “tool” making less progress than an older programmer who might quickly determine what to avoid. And youth can sometimes be unwilling to compromise the reality of programming economics (code actually runs on hardware I’m told) and the beauty of full normalization. (Hint: your college prof was wrong. Talk to an experienced dba and she will speak the truth. Normalization is a goal like reaching the axis on an exponential curve.)

Currently I am trying to catch up with my team on Python and Django (they have really left me in the dust at the moment) I enjoyed this quote from DRY:

My biggest programming headaches have always come from abstractly struggling with “how can I write a good general solution to this problem”, even though I only know of one place where it’s definitely going to be used. “I’d better think of a general solution now,” I think, “or I’ll have to copy-and-paste-and-change code!” But it’s absurd to try to come up with a general solution without knowing more about the different varieties of the problem that exist (or will exist) in the system.

It’s a battle of two really strong urges - OnceAndOnlyOnce vs avoiding Premature Generalization. Do I duplicate for now and try to live with the duplication for a while, or violate YagNi and come up with some half-cocked generalized solution? It’s a tough one, because almost all programmers hate duplication; it’s a sort of primordial programming urge.

However, even though CopyAndPasteProgramming can be expensive to clean up, so is a botched “general solution” – and copy and paste is far cheaper up front. So I also am in favour of temporary duplication, to be refactored when you have a clearer view of the situation. – MatthewBennett

In our shop I have always called it “do it once for all time for all users.” But it means the same thing. Repeating yourself and not solving issues at the root level is a waste of time. I can’t tell you how awesome it is to not have to explicitly declare getters and setters in Python (vs classic ASP where classes don’t even have inheritance.).

Yet there is a catch. At the beginning of a project or approaching a new industry you can’t really do “root cause analysis” because you don’t have any data. To requote the quote above -

However, even though CopyAndPasteProgramming can be expensive to clean up, so is a botched “general solution” – and copy and paste is far cheaper up front. So I also am in favour of temporary duplication, to be refactored when you have a clearer view of the situation. – MatthewBennett

- this balance is the solution and yes it is a bit messy. If the goal of programming is to make a profit then you can’t just argue philosophy without discussing the economics of it. Economics as in money. And economics as in sometimes duplicate code or duplication of data just runs faster on the servers, increases your search engine rankings and lowers your operating costs. I can live with a bit of duplication for that reward.

Often the best solution is to collect data and slam it together and then identify the best organizational structure before the corpus gets too large. Programming classes or actual data both. A filing system for terrabytes of photos and videos for example. It is a balance between the default import settings of all of the hardware you use and the need to compartmentalize source and work product for portability and backups. Yes, you have to compromise to the machines somewhat because you can’t change the settings on every other camera in the world.

Let the data build up a bit. Don’t fight the hardware. Live with some duplication. Then generalize and normalize as best you can. Balance. “Mind as Water” as Lee would say.

delete

I Just Need a Website, That’s All I Need

caller: I was calling about a web site

developer: cool, that’s what we do. how can I help?

caller: I have a simple site and I need some updates. not much really, just a few changes. is that something you do?

developer: yes, what is the url?

caller: well I’ll need you to sign an NDA before I give you the url. can I fax it over?

developer: no (thinks: “do I still have a fax to email gateway working? hmmm”)

caller: what?

developer: we just met and you want to fist bump attorneys?

caller: no, i just don’t know how else to protect my intellectual property!

developer: you have a site now, right?

caller: yes

developer: live on the internet?

caller: yes

developer: …… long pause…..

caller: ok, I see your point.

…. 45 minutes of spec requests and contract pre-negotiation convo takes place here….

caller: so basically that’s it. my brother-in-law said he could build it for $225 dollars but I wanted to call around and get a few options to see if I could reduce the cost. He’s not very good actually.

Thoughts going through your head as the dev:

  1. developer (option 1): so you have a job board and you want to enhance a few features of monster.com to allow for a commission and affiliate structure?
  2. developer (option 2): so you have a great e-commerce idea, have been reviewing amazon.com and found a few ways to improve on their theories to sell widgets?
  3. developer (opti0n 3): so you want to have a self sustaining site that makes you money with no effort invested while you work at your current job realizing the money-for-nothing potential advertised on TV?

Resolution: have you heard of Crowdspring?

#respect #withAllDueRespect

delete

iPhone Apps Make 4 to 6k Total?

And THIS is why we don’t make iPhone apps:

With more than 350,000 apps available on Apple’s digital store, game creators are finding it tough to attract attention despite tens of millions of potential customers who own Apple gadgets, he said.
“They have over-encouraged supply,” Hawkins said on a panel at the conference. Using statistics that Apple has made public, Hawkins calculated that each app earns, on average, about $4,000.
“Four thousand per application: Do you see a problem with that?” he asked the audience. “That doesn’t even pay for a really good foosball table.”
Apple said Wednesday it has doled $2 billion out to app developers, which could put the average payout closer to $5,700. Either way, Hawkins said he believes the math makes it difficult for creators of apps to turn a profit.

Incidentally, depending on the complexity of the App you will get quotes from 10k for a “brochure” app all the way up to 250k. Even on the low end you are looking at a loss. This isn’t to deny that Angry Birds won the lotto and hit it big. But think of making iPhone apps more like trying to get into the NFL. You might. But the odds are stacked against you and the competition is fierce.

delete

the rules driving python

  1. Borrow ideas from elsewhere whenever it makes sense.
  2. “Things should be as simple as possible, but no simpler.” (Einstein)
  3. Do one thing well (the ‘UNIX philosophy’). And that was to create a great programming language that can be used anywhere.
  4. Don’t fret too much about performance – plan to optimise later when needed.
  5. Don’t fight the environment and go with the flow.
  6. Don’t try for perfection because ‘good enough’ is often just that.
  7. (Hence) it’s okay to cut corners sometimes, especially if you can do it right later.
  8. The Python implementation should not be tied to a particular platform. It’s okay if some functionality is not always available, but the core should work everywhere.
  9. Don’t bother users with details that the machine can handle.
  10. A large complex system should have multiple levels of extensibility. This maximizes the opportunities for users, sophisticated or not, to help themselves.
  11. Errors should not be fatal. That is, user code should be able to recover from error conditions as long as the virtual machine is still functional. At the same time, errors should not pass silently.
  12. A bug in the user’s Python code should never be allowed to lead to undefined behavior of the Python interpreter; a core dump is never the user’s fault.

- LinuxUser, Python, the Universal Programming Language paraphrasing Guido van Rossum