2016-01-20 5 views
7

पर सीरियलज़ेबल अलगाव उल्लंघन मेरे पास एक बहुत बड़ा रेडशिफ्ट डेटाबेस है जिसमें HTTP अनुरोध डेटा की अरबों पंक्तियां हैं।रेडशिफ्ट: तालिका

  • ip_address
  • city
  • state
  • country

मैं एक अजगर प्रक्रिया के अनुसार एक बार चल रहा है:

मैं एक मेज requests जो कुछ महत्वपूर्ण क्षेत्रों है कहा जाता है दिन, जो सभी डी पकड़ता है अलंकृत पंक्तियां जिन्हें अभी तक भूगर्भित नहीं किया गया है (कोई शहर/राज्य/देश की जानकारी नहीं है), और फिर Google के जियोकोडिंग एपीआई के माध्यम से प्रत्येक आईपी पते को geocode करने का प्रयास करता है।

यह प्रक्रिया (स्यूडोकोड) इस तरह दिखता है:

for ip_address in ips_to_geocode: 
    country, state, city = geocode_ip_address(ip_address) 
    execute_transaction(''' 
     UPDATE requests 
     SET ip_country = %s, ip_state = %s, ip_city = %s 
     WHERE ip_address = %s 
    ''') 

इस कोड चल रहा है, मैं अक्सर त्रुटियों निम्नलिखित की तरह प्राप्त करते हैं:

psycopg2.InternalError: 1023 
DETAIL: Serializable isolation violation on table - 108263, transactions forming the cycle are: 647671, 647682 (pid:23880) 

मैं इस संभालने हूँ है, क्योंकि मैं अन्य मेरी तालिका में लगातार HTTP अनुरोधों को लॉगिंग करने की प्रक्रिया करता है, इसलिए जब मैं अपना अद्यतन विवरण निष्पादित करने का प्रयास करता हूं, तो यह उस IP पते के साथ सभी पंक्तियों का चयन करने में असमर्थ है, जिसे मैं अपडेट करना चाहता हूं।

मेरा प्रश्न यह है: मैं इन रिकॉर्ड्स को एक ऐसे तरीके से अपडेट करने के लिए क्या कर सकता हूं जो नियमित रूप से विफल रहेगा?

उत्तर

3

आपका कोड Redshift के serializable अलगाव स्तर का उल्लंघन कर रहा है। आपको यह सुनिश्चित करने की ज़रूरत है कि आपका कोड सभी खुले लेनदेन बंद करने से पहले एक ही टेबल पर एकाधिक लेनदेन खोलने की कोशिश नहीं कर रहा है।

आप प्रत्येक लेनदेन में तालिका को लॉक करके इसे प्राप्त कर सकते हैं ताकि खुले लेनदेन बंद होने तक अपडेट के लिए कोई अन्य लेन-देन तालिका तक पहुंच न सके। सुनिश्चित नहीं है कि आपका कोड आर्किटेक्टेड (सिंक्रोनस या असिंक्रोनस) कैसे है, लेकिन यह रन टाइम बढ़ाएगा क्योंकि प्रत्येक लॉक दूसरों को लेनदेन खत्म होने तक प्रतीक्षा करने के लिए मजबूर करेगा।

देखें: http://docs.aws.amazon.com/redshift/latest/dg/r_LOCK.html

0

या तो आप एक नया सत्र शुरू जब आप एक ही मेज पर दूसरा अद्यतन करते हैं या आप 'प्रतिबद्ध' के लिए एक बार आप लेन-देन पूरा हो गया है है।

आप अपडेट शुरू करने से पहले सेट autocommit = लिख सकते हैं।

0

बस मेरे कोड पर एक ही मुद्दा मिल गया है, और thats मैं इसे कैसे तय:

सबसे पहली बात, यह इस त्रुटि कोड का मतलब है कि आप लाल विचलन में समवर्ती संचालन करने के लिए कोशिश कर रहे हैं पता करने के लिए अच्छा है। जब आप पहले पूछे जाने से पहले तालिका में दूसरी क्वेरी करते हैं तो आपने कुछ क्षण पहले किया था, उदाहरण के लिए, एक ऐसा मामला है जहां आपको इस तरह की त्रुटि मिल जाएगी (वह मेरा मामला था)।

अच्छी खबर यह है कि रेडशिफ्ट ऑपरेशंस को क्रमबद्ध करने का एक आसान तरीका है! आपको बस LOCK कमांड का उपयोग करने की आवश्यकता है। redshift LOCK command के लिए अमेज़ॅन प्रलेखन यहां दिया गया है। यह मूल रूप से अगले ऑपरेशन को तब तक इंतजार कर रहा है जब तक कि पिछला बंद न हो जाए। ध्यान दें कि, इस कमांड का उपयोग करके आपकी स्क्रिप्ट स्वाभाविक रूप से थोड़ी धीमी हो जाएगी।

अंत में, मेरे लिए व्यावहारिक समाधान था: मैंने क्वेरी संदेशों से पहले LOCK कमांड डाला (उसी स्ट्रिंग में, ';' से अलग)। कुछ इस तरह:

LOCK table_name; SELECT * from ...

और तुम जाने के लिए अच्छा होना चाहिए! मुझे उम्मीद है इससे आपको मदद मिली होगी।

संबंधित मुद्दे