POSKeyError no Zope Object DataBase? (ZODB)

Aviso: se você está lendo essa página, está com um POSKeyError e não tem backup atualizado, comece a se preocupar. O procedimento a seguir não garante nada e deve ser considerado como a última alternativa, quando por algum motivo único backup atualizado que você tinha não funciona mais e, para não perder tudo, tenta-se recuperar algo de um banco de dados corrompido. Faça sua parte: mantenha seu backup em dia!

Em ocorrências desse erro, recomenda-se:

1) Tentar reindexar os ZODBs, apagando e reconstruindo os índices.

Apesar dessa tentativa muitas vezes não ser suficiente, ela permite a detecção de problemas físicos no banco de dados (o que ocorre quando temos, por exemplo, um HD defeituoso ou problemas de comunicação de rede, ambos possibilidades bastante remotas MAS QUE ACONTECEM).

Para reindexar os indices, fazemos (na raiz da instância):

   ./bin/zopectl stop
   rm ./var/Data.fs.index ./var/Data.fs.tmp ./var/Data.fs.tmp" 
   ./bin/zopectl start

2) Não havendo problemas físicos, é necessário investigar a integridade dos objetos persistidos.

Para isso, com Zope em modo debug, desenvolve-se um script em linha de comando para descobrir qual objeto está corrompido. Esse objeto tem que ser apagado.

Há tutoriais (um tanto desatualizados) que explicam como fazer isso em: http://www.zopelabs.com/cookbook/1095965033

Notem que no tutorial, a raiz do zope é na verdade denotada pelo objeto “app” e não como “root” e que a API de transações mudou para “import transaction; transaction.commit()”

Guardar os logs de todos os procedimentos durante a correção do problema.

Seguem procedimentos adotados durante a correção do POSKeyError (usando zopectl debug)

obj = app.portal
for id,val in obj.objectItems():

...try: val.getId()

...except: break

...
'portal_actions'
'portal_catalog'
'portal_memberdata'
'portal_skins'
'portal_types'
'portal_undo'
'portal_url'
'portal_workflow'
'portal_discussion'
'portal_membership'
'portal_registration'
'portal_properties'
'portal_metadata'
'portal_syndication'
'plone_utils'
'portal_factory'
'portal_migration'
'portal_actionicons'
'portal_calendar'
'portal_quickinstaller'
'portal_groups'
'portal_groupdata'
'cookie_authentication'
'content_type_registry'
'Members'
'acl_users'
'RAMCache'
'portal_interface'
'portal_controlpanel'
'portal_form_controller'
'portal_css'
'portal_javascripts'
'translation_service'
'MailHost'
'mimetypes_registry'
'portal_transforms'
'archetype_tool'
'uid_catalog'
'reference_catalog'
'portal_atct'
'kupu_library_tool'
'portal_uidannotation'
'portal_uidgenerator'
'portal_uidhandler'
'error_log'
'portal_ploneboard'
'portal_publicator'
'sin_tool'
'portal_popoll'
'portal_cssmanager'
'portal_ombudsman'
'portal_windowZ'
'portal_previsao'
'a-assembleia'
'deputados-estaduais'
'processo-legislativo'
'legislacao'
'diario-oficial'
'estudos'
'licitacoes'
'utilidades'
2009-12-16 14:05:36 ERROR ZODB.Connection Couldn't load state for 0x2a7f
Traceback (most recent call last):
  File "/usr/lib/zope2.8/lib/python/ZODB/Connection.py", line 704, in setstate
    self._setstate(obj)
  File "/usr/lib/zope2.8/lib/python/ZODB/Connection.py", line 760, in _setstate
    self._reader.setGhostState(obj, p)
  File "/usr/lib/zope2.8/lib/python/ZODB/serialize.py", line 495, in
setGhostState
    state = self.getState(pickle)
  File "/usr/lib/zope2.8/lib/python/ZODB/serialize.py", line 488, in getState
    return unpickler.load()
  File "/usr/lib/zope2.8/lib/python/ZODB/serialize.py", line 436, in
_persistent_load
    return self._conn.get(oid)
  File "/usr/lib/zope2.8/lib/python/ZODB/Connection.py", line 207, in get
    p, serial = self._storage.load(oid, self._version)
  File "/usr/lib/zope2.8/lib/python/ZODB/FileStorage/FileStorage.py",
line 548, in load
    pos = self._lookup_pos(oid)
  File "/usr/lib/zope2.8/lib/python/ZODB/FileStorage/FileStorage.py",
line 514, in _lookup_pos
    raise POSKeyError(oid)
POSKeyError: 0x0358f3
id
'imagens'

obj._objects=tuple(filter(lambda i,n=id: i['id']!=n, obj._objects))

delattr(obj,id)

import transaction

transaction.commit()

E, finalmente, para testar se está tudo OK (fazendo um traverse dos 3 primeiros niveis do site...)

for id1,val1 in app.objectItems():
  "*" * 80
  id1, val1
  for id2,val2 in val1.objectItems():
    "*" * 80
    id2, val2
    for id3,val3 in val2.objectItems():
      val3.getId()

É necessário remover os objetos corrompidos e depois restaurar os dados apagados de um backup antigo, usando exportação e importação em formato zexp. Se você não tem backup e não tem nem um Data.fs, o que precisou ser apagado foi realmente perdido. Convém ressaltar que a importação pode não funcionar se o portal_catalog estiver corrompido também; e, nesse caso, é necessário remontar os índices manualmente depois de importar (apagando o índice e recriando o mesmo, reindexando todos os objetos DEPOIS de importar o zexp).

Minha recomendação para evitar que problemas semelhantes ocorram novamente é a seguinte: manter o sistema operacional, python, zope e plone atualizados.

No que diz respeito a esse problema em especial, é importante estar rodando uma versão atualizada do ZEO/ZODB, que trata melhor referências de objetos entre diferentes ZODB. Há outros motivos para essa atualização, como recente vulnerabilidade de segurança para a qual já existe correção.

http://archives.free.net.ph/message/20090901.101213.46a0454e.pt.html e http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2009-2701

Fabiano Weimar dos Santos [Xiru]

Última modificação 9 anos atrás Última modificação em 22/12/2009 15:54:12
 

The contents and data of this website are published under license:
Creative Commons 4.0 Brasil - Atribuir Fonte - Compartilhar Igual.