카테고리 없음
AWS DMS (Database Migration Service)를 못믿어 데이터베이스 테이블 비교 코드를 만들어 보았습니다.
jhansol
2025. 7. 9. 00:34
안녕하세요?
정말 오랜만에 블로그에 글을 올립니다. 그 동안 바쁘다는 핑계로 기억을 박제하지 못했네요. ㅠㅠ
저는 요즘 개발 업무보다 회사의 운영 방침에 따라 AWS 인프라 관리, 마이그레이션관련 일에 몰두하고 있습니다. 개발 업무를 하고픈데, 업무가 이상하게 흘러가는 듯 합니다. 암튼 지금은 이 일을 하고 있습니다.
마이그레이션 작업에서 가장 신경이 쓰이는 부분이 운영 중인 데이터베이스를 다른 서버 또는 다른 계정으로 마이그레이션 하는 부분이라고 생각합니다. 지금 이 작업을 하고 있는데, 몇일 전 하나의 프로젝트(서비스) 데이터를 이동하는 중 데이터가 모두 복재가 되지 않아 소스에서 덤프를 뜨서 대상 데이터베이스에 복원한 적이 있습니다. 이 후로 DMS로 마이그레이션하고, 복제하는 작업을 신뢰할 수 없게 되었습니다.
그래서 만들어 봤습니다.
아래의 코드는 간단하게 ChatGPT를 이용하여 코드를 작성하고, 약간 수정한 것입니다. 잘 동작합니다.
const mariadb = require('mariadb');
const db1Config = {
host: '127.0.0.1',
port: 63306, // ✅ 포트 번호 추가
user: 'admin',
password: 'xxxxxxxx!',
database: 'xxxxxxxx',
};
const db2Config = {
host: '127.0.0.1',
port: 33306, // ✅ 포트 번호 추가
user: 'admin',
password: 'xxxxxxx!',
database: 'xxxxxxx',
};
async function getTableRowCounts(pool, database) {
const conn = await pool.getConnection();
try {
const tables = await conn.query(`
SELECT table_name
FROM information_schema.tables
WHERE table_schema = ?
`, [database]);
const counts = {};
for (const row of tables) {
const table = row.table_name;
const result = await conn.query(`SELECT COUNT(*) as count FROM \`${table}\``);
counts[table] = result[0].count;
}
return counts;
} finally {
conn.release();
}
}
async function compareDatabases() {
const pool1 = mariadb.createPool(db1Config);
const pool2 = mariadb.createPool(db2Config);
try {
const [counts1, counts2] = await Promise.all([
getTableRowCounts(pool1, db1Config.database),
getTableRowCounts(pool2, db2Config.database),
]);
const allTables = new Set([...Object.keys(counts1), ...Object.keys(counts2)]);
let identical = true;
for (const table of allTables) {
const count1 = counts1[table];
const count2 = counts2[table];
if (count1 === undefined) {
console.log(`❌ Table '${table}' missing in DB1`);
identical = false;
} else if (count2 === undefined) {
console.log(`❌ Table '${table}' missing in DB2`);
identical = false;
} else if (count1 !== count2) {
console.log(`❌ Table '${table}' row count differs: DB1=${count1}, DB2=${count2}`);
identical = false;
} else {
console.log(`✅ Table '${table}' matches with ${count1} rows`);
}
}
console.log('\n✅ Databases are ' + (identical ? 'identical' : 'different') + ' in structure and row count.');
} catch (err) {
console.error('Error:', err);
} finally {
await pool1.end();
await pool2.end();
}
}
compareDatabases();
그리고 package.json은 아래와 같습니다.
{
"name": "db_compare",
"version": "1.0.0",
"description": "Compare database",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"mariadb": "^3.4.4"
}
}
잘 돌아갑니다. 그리고 테이블 이름과 테이블에 저장된 레코드 수가 모두 일치한다고 나요네요. 이로서 두 데이터베이스는 동일하다고 볼 수 있을 것 같습니다.
그리고 두 데이터베이스는 AWS 프라이빗 서브넷에 있어 SSH 명령을 이용하여 터널링하여 접속해서 체크했습니다.
결과는 아래와 같습니다.
node index.js
✅ Table 'dx_lecture_enrollments' matches with 0 rows
✅ Table 'member_companies' matches with 1 rows
✅ Table 'online_edu_lecture_study_logs' matches with 0 rows
✅ Table 'password_resets' matches with 0 rows
✅ Table 'performance_dx_job_transition_rates' matches with 0 rows
✅ Table 'experience_images' matches with 0 rows
✅ Table 'metabus_teaching_plans' matches with 0 rows
✅ Table 'ncs_code' matches with 13351 rows
✅ Table 'base_inspects' matches with 0 rows
✅ Table 'migrations' matches with 97 rows
✅ Table 'resume_activities' matches with 0 rows
✅ Table 'personal_access_tokens' matches with 0 rows
✅ Table 'online_edu_contents' matches with 0 rows
✅ Table 'type_inspects' matches with 0 rows
✅ Table 'failed_jobs' matches with 0 rows
✅ Table 'competences' matches with 0 rows
✅ Table 'metabus_classes' matches with 0 rows
✅ Table 'dx_lecture_schedules' matches with 17 rows
✅ Table 'univs' matches with 4 rows
✅ Table 'community_files' matches with 4 rows
✅ Table 'experience_folders' matches with 0 rows
✅ Table 'expert_certifications' matches with 0 rows
✅ Table 'users' matches with 13 rows
✅ Table 'member_company_representative_history' matches with 0 rows
✅ Table 'admins' matches with 4 rows
✅ Table 'metabus_class_times' matches with 0 rows
✅ Table 'report_logs' matches with 0 rows
✅ Table 'digital_badges' matches with 4 rows
✅ Table 'performance_adult_friendly_edu_indexes' matches with 0 rows
✅ Table 'inspect_questions' matches with 256 rows
✅ Table 'resume_languages' matches with 0 rows
✅ Table 'digital_badge_issued_users' matches with 0 rows
✅ Table 'univ_admins' matches with 6 rows
✅ Table 'recruit_job_codes' matches with 1297 rows
✅ Table 'communities' matches with 8 rows
✅ Table 'metabus_class_logs' matches with 0 rows
✅ Table 'performances' matches with 48 rows
✅ Table 'resume_certificates' matches with 0 rows
✅ Table 'metabus_matterports' matches with 4 rows
✅ Table 'expert_histories' matches with 0 rows
✅ Table 'resumes' matches with 0 rows
✅ Table 'resume_careers' matches with 0 rows
✅ Table 'cache' matches with 60 rows
✅ Table 'resume_educations' matches with 0 rows
✅ Table 'ncs_licenses' matches with 21299 rows
✅ Table 'inspect_answers' matches with 0 rows
✅ Table 'dx_lectures' matches with 4 rows
✅ Table 'performance_dx_governance_indexes' matches with 0 rows
✅ Table 'online_edu_content_media' matches with 0 rows
✅ Table 'self_inspects' matches with 0 rows
✅ Table 'performance_active_job_transition_indexes' matches with 0 rows
✅ Table 'metabus_class_users' matches with 0 rows
✅ Table 'cache_locks' matches with 0 rows
✅ Table 'resume_technologies' matches with 0 rows
✅ Table 'digital_badge_configs' matches with 3 rows
✅ Table 'performance_dx_stakeholder_satisfactions' matches with 0 rows
✅ Table 'dx_categories' matches with 21 rows
✅ Table 'sessions' matches with 59 rows
✅ Table 'member_company_certification_status' matches with 2 rows
✅ Table 'recruit_infos' matches with 64099 rows
✅ Table 'performance_dx_employed_startup_rates' matches with 0 rows
✅ Table 'resume_self_introductions' matches with 0 rows
✅ Table 'expert_experiences' matches with 0 rows
✅ Table 'experiences' matches with 0 rows
✅ Table 'resume_awards' matches with 0 rows
✅ Table 'community_comments' matches with 1 rows
✅ Table 'online_edu_lectures' matches with 0 rows
✅ Table 'experts' matches with 0 rows
✅ Table 'platform_histories' matches with 0 rows
✅ Table 'performance_dx_attainment_degree_rates' matches with 0 rows
✅ Table 'performance_dx_completes' matches with 0 rows
✅ Table 'ncs_recommend_keywords' matches with 1083 rows
✅ Table 'ncs_self_inspects' matches with 1114 rows
✅ Databases are identical in structure and row count.