Треба синхронізувати деякі таблиці для того щоб працювати з точною реплікою бази і не навантажувати основний сервер БД.
Цікава задача, довго думав як це зробити. гугління не допомагало і ось прийшло натхнення.
1) спочатку створюємо цільову базу на сервері БД:
sudo -u postgres psql
postgres=
postgres=# CREATE USER [username
] WITH PASSWORD ‘[password
]‘;
postgres=# GRANT ALL PRIVILEGES ON DATABASE [dbname
] TO [username
];
дозволяю зовнішні підключення тут:
sudo nano /etc/postgresql/[version]/main/pg_hba.conf
для дозволу підключатись з іншого хоста додати такий рядок:
host [dbname
] [username
] [IP addr зовнішнього хоста] md5
sudo service postgresql restart
2)далі треба встановити модулі для скрипта
pip install sqlalchemy pyodbc psycopg2
3)у скрипті заповнюємо MSSQL_CONNECTION_LINE POSTGRESQL_CONNECTION_LINE TABLE_NAME
валідними даними:
import time
from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData, select, insert
# constants
# example: mssql+pyodbc://username:password@mssql_server
MSSQL_CONNECTION_LINE = 'mssql+pyodbc://username:password@mssql_server'
# example: postgresql://username:password@postgres_server/dbname
POSTGRESQL_CONNECTION_LINE = 'postgresql://username:password@postgres_server/dbname'
# Define block size for sync
BLOCK_SIZE = 1000
# MSSQL table name to synchronize
TABLE_NAME = 'table_name'
# Connect to MSSQL database
mssql_engine = create_engine(MSSQL_CONNECTION_LINE)
# Connect to PostgreSQL database
postgres_engine = create_engine(POSTGRESQL_CONNECTION_LINE)
# Read metadata from MSSQL
mssql_metadata = MetaData(bind=mssql_engine)
table = Table(TABLE_NAME, mssql_metadata, autoload=True)
# Create table in PostgreSQL if it doesn't exist postgres_metadata = MetaData(bind=postgres_engine) table.metadata = postgres_metadata table.create(checkfirst=True) # because after first run all other runs table exist
# Get total number of rows from MSSQL
mssql_conn = mssql_engine.connect()
row_count = mssql_conn.execute(select([table.c.id]).select_from(table).count()).scalar()
mssql_conn.close()
# Copy data from MSSQL to PostgreSQL in blocks
postgres_conn = postgres_engine.connect()
total_time = 0
for i in range(0, row_count, BLOCK_SIZE):
start_time = time.perf_counter()
data = mssql_conn.execute(select([table]).select_from(table).offset(i).limit(BLOCK_SIZE))
postgres_conn.execute( insert(table).from_select(table.columns.keys(), data)
.on_conflict_do_update( index_elements=table.primary_key,
set_={c: getattr(table.c, c) for c in table.columns.keys()}
)
)
end_time = time.perf_counter()
batch_time = end_time - start_time
postgres_conn.close()
print(f"Table: {TABLE_NAME}")
print(f"Total rows synced: {row_count}")
print(f"Total time: {total_time:.2f} seconds")
Запускаємо скрипт. якщо не буде помилок – виведе в консоль як довго перекачував данні для таблиці. Щонайменше раз треба подивитись щоб дізнатись час синхронізації