1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. Anuncie Aqui
    Anuncie aqui você Também: fdantas@4each.com.br

[Python] How to perform parallel data migration using Python

Discussão em 'Python' iniciado por Stack, Setembro 15, 2024.

  1. Stack

    Stack Membro Participativo

    I want to perform data migration between tables in parallel. For example, I have data for cities A, B, and C. Let's say the data migration takes about 30 minutes. Migration of cities A and B is done at 1 am. Then city C at 1.10 am.

    In the code that I wrote, migration cannot run in parallel. Migration of city C will be done after cities A and B are finished. How can I do that? The following is the generated data that I created:

    import pandas as pd import random

    # Defining column names
    columns = ['ID', 'Name', 'City', 'City_ID', 'Revenue']

    # List of cities and corresponding city IDs
    cities = {
    'New York': 1,
    'Los Angeles': 2,
    'Chicago': 3,
    'Houston': 4,
    'Phoenix': 5 }

    # Generating 1000000 rows of dummy data
    data = {
    'ID': range(1, 1000001),
    'Name': [f"Customer_{i}" for i in range(1, 1000001)],
    'City': [random.choice(list(cities.keys())) for _ in range(1000000)],
    'Revenue': [round(random.uniform(20.0, 500.0), 2) for _ in range(1000000)] }

    # Creating City_ID based on the City column
    data['City_ID'] = [cities[city] for city in data['City']]

    # Creating DataFrame
    df = pd.DataFrame(data)

    # Displaying the first few rows of the DataFrame
    print(df.head())

    # Optionally, you can save the data to a CSV file
    df.to_csv('D:/INSAN/Document Project/dummy_data.csv', index=False)


    city_flagging table

    1 New York 0 0 0
    2 Los Angeles 0 0 0
    4 Houston 0 0 0
    5 Phoenix 0 0 0
    3 Chicago 1 0 0

    Here is the code for data migration:

    import pyodbc
    import datetime
    import time
    import concurrent.futures

    # Save migrated cities
    migrated_city_ids = set()

    # Function to get is_available = 1 status from database
    def check_flagging_status():
    conn = pyodbc.connect('Driver={PostgreSQL ODBC Driver(UNICODE)};server=localhost;port=5433;database=postgres;uid=postgres;pwd=postgres')
    cursor = conn.cursor()

    query = "SELECT * FROM city_flagging WHERE is_available = 1 AND is_running = 0"
    cursor.execute(query)

    available_cabangs = cursor.fetchall()

    cursor.close()
    conn.close()

    return available_cabangs

    # Function to update is_running and is_success status in city_flagging table
    def update_flagging_status(city_id, is_running=None, is_success=None):
    conn = pyodbc.connect('Driver={PostgreSQL ODBC Driver(UNICODE)};server=localhost;port=5433;database=postgres;uid=postgres;pwd=postgres')
    cursor = conn.cursor()

    try:
    if is_running is not None:
    query = "UPDATE city_flagging SET is_running = ? WHERE city_id = ?"
    cursor.execute(query, (is_running, city_id))

    if is_success is not None:
    query = "UPDATE city_flagging SET is_success = ? WHERE city_id = ?"
    cursor.execute(query, (is_success, city_id))

    conn.commit()
    except Exception as e:
    print(f"Error while updating flagging status for city {city_id}: {e}")
    finally:
    cursor.close()
    conn.close()

    # Single city data migration function
    def migrate_data(city_id, city_name):
    if city_id in migrated_city_ids:
    print(f"City {city_id} already migrated before, skip migration.")
    return

    # Update is_running to 1 (migration process is running)
    update_flagging_status(city_id, is_running=1)

    date = datetime.datetime.now().date()
    start_datetime = datetime.datetime.now()

    conn_old = pyodbc.connect('Driver={PostgreSQL ODBC Driver(UNICODE)};server=localhost;port=5433;database=postgres;uid=postgres;pwd=postgres')
    cursor_old = conn_old.cursor()

    conn_new = pyodbc.connect('Driver={PostgreSQL ODBC Driver(UNICODE)};server=localhost;port=5433;database=postgres;uid=postgres;pwd=postgres')
    cursor_new = conn_new.cursor()

    try:
    query = f"SELECT * FROM dummy_data WHERE city_id = '{city_id}'"
    cursor_old.execute(query)
    transaksi_data = cursor_old.fetchall()

    print(f"Data migration for city {city_id} is in progress.")
    insert_query = "INSERT INTO dummy_data_1 (id, name, city, revenue, city_id) VALUES (?, ?, ?, ?, ?)"
    cursor_new.executemany(insert_query, transaksi_data)

    conn_new.commit()

    end_datetime = datetime.datetime.now()

    log_query = """
    INSERT INTO migration_log (date, city_id, city_name, start_datetime, end_datetime)
    VALUES (?, ?, ?, ?, ?)
    """
    cursor_new.execute(log_query, (date, city_id, city_name, start_datetime, end_datetime))
    conn_new.commit()

    # Update is_success menjadi 1 (migrasi berhasil)
    update_flagging_status(city_id, is_success=1)

    migrated_city_ids.add(city_id)
    print(f"Data migration for city {city_id} is complete.")

    except Exception as e:
    print(f"Error while migrating data for city {city_id}: {e}")

    finally:
    cursor_old.close()
    conn_old.close()
    cursor_new.close()
    conn_new.close()

    # Function to start migration
    def start_migration():
    city_list = check_flagging_status()

    if not city_list:
    print("There are no cities available for migration.")
    return False # Tidak ada city yang tersedia

    with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    for city in city_list:
    city_id = city[0]
    city_name = city[1]
    executor.submit(migrate_data, city_id, city_name)

    return True # There is a migration underway

    # Function for periodic checks
    def continuous_check(interval_seconds=2, max_no_migration_attempts=3):
    no_migration_attempts = 0

    while no_migration_attempts < max_no_migration_attempts:
    print("Checking flagging city status...")
    migration_started = start_migration() # Check and migrate if there is a new city available

    if migration_started:
    no_migration_attempts = 0 # Reset trial if there is a migration running
    else:
    no_migration_attempts += 1 # TAdd trial if no city available

    if no_migration_attempts >= max_no_migration_attempts:
    print("No cities available for migration in multiple attempts. Stopping the process.")
    break

    time.sleep(interval_seconds) # Wait for the specified interval

    # Run periodic checks in parallel
    continuous_check(1, 3)

    Continue reading...

Compartilhe esta Página