Мне нужна помощь в понимании того, как Python и postgres обрабатывают транзакции и массовые вставки, особенно при вставке нескольких наборов данных в одну транзакцию.Окружение:
- Windows 7 64-битная
- Python 3.2
- Postgresql 9.1
- psycopg2
Вот мой сценарийЯ преобразовываю данные из одной базы данных (оракула) в строки XML и вставляю эти данные в новую базу данных (postgres).Это большой набор данных, поэтому я пытаюсь оптимизировать некоторые из моих вставок.Многие из этих данных я рассматриваю объекты библиотечного типа, поэтому у меня есть таблица библиотеки, а затем таблицы для моих метаданных xml и содержимого xml, поля для этих данных - это текстовые типы в базе данных.Я вытаскиваю данные из оракула, а затем создаю словари данных, которые мне нужно вставить.У меня есть 3 оператора вставки, первая вставка создает запись в таблице библиотеки с использованием серийного идентификатора, и этот идентификатор необходим для связи в следующих двух запросах, которые вставляют XML в таблицы метаданных и содержимого.Вот пример того, о чем я говорю:
for inputKey in libDataDict.keys():
metaString = libDataDict[inputKey][0]
contentString = libDataDict[inputKey][1]
insertLibDataList.append({'objIdent':"%s" % inputKey, 'objName':"%s" % inputKey, objType':libType})
insertMetadataDataList.append({'objIdent':inputKey,'objMetadata':metaString})
insertContentDataList.append({'objIdent':inputKey, 'objContent':contentString})
dataDict['cmsLibInsert'] = insertLibDataList
dataDict['cmsLibMetadataInsert'] = insertMetadataDataList
dataDict['cmsLibContentInsert'] = insertContentDataList
sqlDict[0] = {'sqlString':"insert into cms_libraries (cms_library_ident, cms_library_name, cms_library_type_id, cms_library_status_id) \
values (%(objIdent)s, %(objName)s, (select id from cms_library_types where cms_library_type_name = %(objType)s), \
(select id from cms_library_status where cms_library_status_name = 'active'))", 'data':dataDict['cmsLibInsert']}
sqlDict[1] = {'sqlString':"insert into cms_library_metadata (cms_library_id, cms_library_metadata_data) values \
((select id from cms_libraries where cms_library_ident = %(objIdent)s), $$%(objMetadata)s$$)", \
'data':dataDict['cmsLibMetadataInsert']}
sqlDict[2] = {'sqlString':"insert into cms_library_content (cms_library_id, cms_library_content_data) values \
((select id from cms_libraries where cms_library_ident = %(objIdent)s), $$%(objContent)s$$)", \
'data':dataDict['cmsLibContentInsert']}
bulkLoadData(myConfig['pgConn'], myConfig['pgCursor'], sqlDict)
Проблема, с которой я сталкиваюсь, - это когда я запускаю первый запрос (sqlDict [0]) и выполняю вставку, все работает нормально, пока яон отделяется и фиксируется, прежде чем я запусту следующие два.В идеале я хотел бы, чтобы все эти запросы выполнялись в одной транзакции, но это не удалось, поскольку он не может найти идентификатор из таблицы cms_libraries для 2-го и 3-го запросов.Вот мой текущий код вставки:
def bulkLoadData(dbConn, dbCursor, sqlDict):
try:
libInsertSql = sqlDict.pop(0)
dbSql = libInsertSql['sqlString']
data = libInsertSql['data']
dbCursor.executemany(dbSql, data)
dbConn.commit()
for sqlKey in sqlDict:
dbSql = sqlDict[sqlKey]['sqlString']
data = sqlDict[sqlKey]['data']
dbCursor.executemany(dbSql, data)
dbConn.commit()
Ранее я добавлял значения в запрос, а затем выполнял запрос для каждой вставки.Когда я делаю это, я могу поместить все это в одну транзакцию, и он находит сгенерированный идентификатор, и все в порядке.Я не понимаю, почему он не находит идентификатор, когда я делаю массовую вставку с executemany ()?Есть ли способ выполнить массовую вставку и два других запроса в одной и той же транзакции?
Я читал эту документацию и искал stackoverflow и Интернет, но не нашел ответа на мою проблему: pyscopg docs , а также postgres: Postgresql string docs
Любая помощь, предложения или комментарии приветствуются.Спасибо, Митч