Оказва се, че проблемът е доста неудобен. Накратко, повечето варианти и видове в типове данни на MySQL низове карта към един тип данни в интерфейса на MySQL с допълнителен BINARY флаг.
По този начин VARCHAR на MySQL , VARBINARY , и низов литерал, преобразуван в същия MySQLdb.constants.FIELD_TYPE.VAR_STRING въведете дефинициите на тип колона, но с допълнителен MySQLdb.constants.FLAG.BINARY флаг, когато типът е VARBINARY или низ, съпоставен с *_bin съпоставяне.
Въпреки че има MySQLdb.constants.FIELD_TYPE.VARCHAR тип, не успях да разбера кога се използва. Както казах, MySQL VARCHAR колоните се съпоставят с FIELD_TYPE.VAR_STRING .
Решението става доста крехко, ако приложението ви използва истински двоични низове (например съхранявате изображения и ги извличате със същата връзка като текста), тъй като предполага декодиране на всички двоични низове в unicode. Въпреки това работи.
Като официални документи гласи:
На практика истинска болка в задника може да бъде процесът на изграждане на свой собствен речник за конвертори. Но можете да импортирате този по подразбиране от MySQLdb.converters.conversions и го поправете или дори го поправете на екземпляр на връзката. Номерът е да премахнете специален конвертор за FLAG.BINARY флаг и добавете декодер за всички случаи. Ако изрично посочите charset параметър за MySQLdb.connect , принуждава use_unicode=1 параметър, който добавя декодера вместо вас, но можете да го направите сами:
>>> con = MySQLdb.connect(**params)
>>> con.converter[FIELD_TYPE.VAR_STRING]
[(128, <type 'str'>), (None, <function string_decoder at 0x01FFA130>)]
>>> con.converter[FIELD_TYPE.VAR_STRING] = [(None, con.string_decoder)]
>>> c = con.cursor()
>>> c.execute("SELECT %s COLLATE utf8_bin", u'м')
1L
>>> c.fetchone()
(u'\u043c',)
Може да се наложи да направите същия хак за FIELD_TYPE.STRING ако е необходимо.
Друго решение е да предадете изрично use_unicode=0 към MySQLdb.connect и да направя всички декодиране във вашия код, но аз не бих.
Надявам се, това може да е полезно за някого.