답변:
매뉴얼에 데이터베이스 복사에 나와있는 것처럼 덤프를 mysql 클라이언트에 직접 파이프 할 수 있습니다.
mysqldump db_name | mysql new_db_name
MyISAM을 사용하는 경우 파일을 복사 할 수 있지만 권장하지는 않습니다. 약간 피하다.
다양한 좋은 다른 답변에서 통합
mysqldump
및 mysql
명령 모두 다음 과 같이 연결 세부 정보를 설정하는 옵션을 허용합니다.
mysqldump -u <user name> --password=<pwd> <original db> | mysql -u <user name> -p <new db>
또한 새 데이터베이스가 아직 존재하지 않으면 미리 데이터베이스를 만들어야합니다 (예 :) echo "create database new_db_name" | mysql -u <dbuser> -p
.
mysqldump -uroot -p database1 | mysql -uroot -p database2
. 두 사람 모두에 대한 프롬프트가 표시되지만 하나만 넣을 수 있습니다. 프롬프트는 다음과 같습니다 Enter password: Enter password:
.. 첫 번째 비밀번호를 제공 한 후 프로세스는 영원히 기다립니다.
MySQL 유틸리티에는 멋진 도구가 포함되어 있습니다 mysqldbcopy
기본적으로 모든 관련 개체 (“테이블, 뷰, 트리거, 이벤트, 프로 시저, 함수 및 데이터베이스 수준 권한 부여”)와 한 DB 서버에서 동일한 서버 또는 다른 서버로의 데이터를 포함하여 DB를 복사하는 가 DB 서버. 실제로 복사되는 내용을 사용자 정의 할 수있는 옵션이 많이 있습니다.
따라서 OP의 질문에 대답하려면 다음을 수행하십시오.
mysqldbcopy \
--source=root:your_password@localhost \
--destination=root:your_password@localhost \
sitedb1:sitedb2
mysqldump
기반 솔루션이 실패했습니다.
sudo apt-get install mysql-utilities
하지만 매우 깔끔합니다. 비밀번호를 제외하고 입력하라는 메시지가 표시됩니까?
mysqldbcopy
비밀번호를 물어볼 수 있는 내장 된 방법이 있는지 모르겠습니다 . 적어도 나는 문서에서 그런 것을 찾을 수 없었습니다. 그래도이 기능을 직접 구축 할 수 있습니다. Bash에서는 다음과 같이 보일 수 있습니다.mysqldbcopy --source=root:"$(read -sp 'Source password: ' && echo $REPLY)"@localhost --destination=root:"$(read -sp 'Destination password: ' && echo $REPLY)"@localhost sitedb1:sitedb2
--force
해야했습니다 mysqldbcopy
. 감사!
mysqladmin create DB_name -u DB_user --password=DB_pass && \
mysqldump -u DB_user --password=DB_pass DB_name | \
mysql -u DB_user --password=DB_pass -h DB_host DB_name
터미널 / 명령 프롬프트에서 명령을 실행해야합니다.
mysqldump -u <user name> -p <pwd> <original db> | mysql -u <user name> <pwd> <new db>
예 : mysqldump -u root test_db1 | mysql -u root test_db2
test_db1을 test_db2에 복사하고 'root'@ 'localhost'에 대한 액세스 권한을 부여합니다.
가장 쉽고 쉬운 방법은 터미널에 이러한 명령을 입력하고 루트 사용자에게 권한을 설정하는 것입니다. 나를 위해 작동합니다 ..!
:~$> mysqldump -u root -p db1 > dump.sql
:~$> mysqladmin -u root -p create db2
:~$> mysql -u root -p db2 < dump.sql
mysqldump -u <user> -p <pwd> db_name | mysql -u <user> -p <pwd> new_db_name
은 큰 데이터베이스에서 문제가 될 수 있습니다.
의사 코드로 사용할 수 있습니다.
FOREACH tbl IN db_a:
CREATE TABLE db_b.tbl LIKE db_a.tbl;
INSERT INTO db_b.tbl SELECT * FROM db_a.tbl;
CREATE TABLE ... SELECT ... 구문을 사용하지 않는 이유는 인덱스를 보존하기 위해서입니다. 물론 이것은 테이블 만 복사합니다. 뷰와 절차는 동일한 방식으로 수행 될 수 있지만 복사되지는 않습니다.
CREATE TABLE을 참조하십시오 .
이 문장은 MySQL 5.1.7에 추가되었지만 위험한 것으로 판명되어 MySQL 5.1.23에서 제거되었습니다. 데이터베이스 이름을 데이터베이스 디렉토리 이름에 맵핑하기 위해 5.1에서 구현 된 인코딩을 사용하기 위해 5.1 이전 데이터베이스를 업그레이드 할 수있게되었습니다. 그러나이 명령문을 사용하면 데이터베이스 컨텐츠가 유실 될 수 있으므로 제거되었습니다. RENAME DATABASE가있는 이전 버전에서는 RENAME DATABASE를 사용하지 마십시오.
새 인코딩으로 데이터베이스 이름을 업그레이드하는 작업을 수행하려면 대신 ALTER DATABASE db_name UPGRADE DATA DIRECTORY NAME을 사용 하십시오 . http://dev.mysql.com/doc/refman/5.1/en/alter-database.html
에서 언급 한 바와 같이 그렉의 대답 , mysqldump db_name | mysql new_db_name
은 IS , 무료 금고, 쉽게 데이터베이스간에 데이터를 전송하는 방법. 그러나 실제로 느립니다 .
데이터를 백업하려는 경우 (이 데이터베이스 나 다른 데이터베이스에서) 데이터를 잃을 여유가 없거나 이외의 테이블을 사용하는 경우을 innodb
사용해야합니다 mysqldump
.
개발할 무언가를 찾고 있다면 모든 데이터베이스를 다른 곳에 백업하고 mysql
모든 것이 잘못되었을 때 제거 및 재설치 (수동으로 가능)를 편안하게 한다면 해결책이있을 것입니다.
좋은 대안을 찾지 못해서 직접 스크립트를 작성했습니다. 나는 이것을 처음으로 작동시키는 데 많은 시간을 보냈으며 지금은 그것을 바꾸는 것이 약간의 두려움을 가지고 있습니다. Innodb 데이터베이스는 이와 같이 복사하여 붙여 넣을 의도가 아닙니다. 작은 변경으로 인해이 방법이 장엄하게 실패합니다. 코드를 완성한 후에도 문제가 없었지만 그렇다고해서 문제가되지는 않습니다.
테스트 한 시스템 (하지만 여전히 실패 할 수 있음) :
sudo
데이터베이스를 복제 할 수있는 충분한 저장 공간이 특권과를 검증을mysqldump
3GB의 데이터베이스에서 사용 mysqldump
하고 mysql
내 컴퓨터에 40~50분 걸릴 것이다. 이 방법을 사용하면 동일한 프로세스는 ~ 8 분만 소요됩니다.
우리는 SQL 변경 사항을 코드와 함께 저장했으며 업그레이드 프로세스는 프로덕션 및 개발 모두에서 자동화되며 각 변경 사항 집합은 오류가있는 경우 복원 할 데이터베이스 백업을 만듭니다. 우리가 겪었던 한 가지 문제는 데이터베이스 변경으로 장기 프로젝트를 수행 할 때 버그를 수정하기 위해 그 중간에 브랜치를 전환해야한다는 것이 었습니다.
과거에는 모든 지점에 단일 데이터베이스를 사용했으며 새로운 데이터베이스 변경 사항과 호환되지 않는 지점으로 전환 할 때마다 데이터베이스를 다시 작성해야했습니다. 다시 전환 할 때 업그레이드를 다시 실행해야합니다.
mysqldump
다른 지점에 대해 데이터베이스를 복제 하려고 시도했지만 대기 시간이 너무 길어서 (40-50 분) 그 동안 다른 작업을 수행 할 수 없었습니다.
이 솔루션은 데이터베이스 복제 시간을 시간의 1/5로 단축했습니다 (긴 점심 대신 커피와 화장실을 생각하십시오).
호환되지 않는 데이터베이스 변경 사항이있는 지점 간 전환은 단일 데이터베이스에서 50 분 이상 걸리지 만이 mysqldump
코드를 사용하여 초기 설정 시간이 지나면 전혀 시간 이 없습니다. 이 코드는 ~보다 5 배 빠릅니다 mysqldump
.
다음은 몇 가지 일반적인 작업과 각 방법에 소요되는 시간입니다.
mysqldump
: 50-60 분master
하고 버그 수정으로 전환 하여 기능 분기를 편집하고 병합하십시오.mysqldump
: 50-60 분master
편집하는 동안 버그 수정으로 5 번 전환하여 병합하십시오.mysqldump
: 50-60 분위의 모든 내용을 읽고 이해하지 않는 한 이것을 사용하지 마십시오.
#!/bin/bash
set -e
# This script taken from: https://stackoverflow.com/a/57528198/526741
function now {
date "+%H:%M:%S";
}
# Leading space sets messages off from step progress.
echosuccess () {
printf "\e[0;32m %s: %s\e[0m\n" "$(now)" "$1"
sleep .1
}
echowarn () {
printf "\e[0;33m %s: %s\e[0m\n" "$(now)" "$1"
sleep .1
}
echoerror () {
printf "\e[0;31m %s: %s\e[0m\n" "$(now)" "$1"
sleep .1
}
echonotice () {
printf "\e[0;94m %s: %s\e[0m\n" "$(now)" "$1"
sleep .1
}
echoinstructions () {
printf "\e[0;104m %s: %s\e[0m\n" "$(now)" "$1"
sleep .1
}
echostep () {
printf "\e[0;90mStep %s of 13:\e[0m\n" "$1"
sleep .1
}
MYSQL_CNF_PATH='/etc/mysql/mysql.conf.d/recovery.cnf'
OLD_DB='YOUR_DATABASE_NAME'
USER='YOUR_MYSQL_USER'
# You can change NEW_DB to whatever you like
# Right now, it will append the current git branch name to the existing database name
BRANCH=`git rev-parse --abbrev-ref HEAD`
NEW_DB="${OLD_DB}__$BRANCH"
THIS_DIR=./site/upgrades
DB_CREATED=false
tmp_file () {
printf "$THIS_DIR/$NEW_DB.%s" "$1"
}
sql_on_new_db () {
mysql $NEW_DB --unbuffered --skip-column-names -u root -p$PASS 2>> $(tmp_file 'errors.log')
}
general_cleanup () {
echoinstructions 'Leave this running while things are cleaned up...'
if [ -f $(tmp_file 'errors.log') ]; then
echowarn 'Additional warnings and errors:'
cat $(tmp_file 'errors.log')
fi
for f in $THIS_DIR/$NEW_DB.*; do
echonotice 'Deleting temporary files created for transfer...'
rm -f $THIS_DIR/$NEW_DB.*
break
done
echonotice 'Done!'
echoinstructions "You can close this now :)"
}
error_cleanup () {
exitcode=$?
# Just in case script was exited while in a prompt
echo
if [ "$exitcode" == "0" ]; then
echoerror "Script exited prematurely, but exit code was '0'."
fi
echoerror "The following command on line ${BASH_LINENO[0]} exited with code $exitcode:"
echo " $BASH_COMMAND"
if [ "$DB_CREATED" = true ]; then
echo
echonotice "Dropping database \`$NEW_DB\` if created..."
echo "DROP DATABASE \`$NEW_DB\`;" | sql_on_new_db || echoerror "Could not drop database \`$NEW_DB\` (see warnings)"
fi
general_cleanup
exit $exitcode
}
trap error_cleanup EXIT
mysql_path () {
printf "/var/lib/mysql/"
}
old_db_path () {
printf "%s%s/" "$(mysql_path)" "$OLD_DB"
}
new_db_path () {
printf "%s%s/" "$(mysql_path)" "$NEW_DB"
}
get_tables () {
(sudo find /var/lib/mysql/$OLD_DB -name "*.frm" -printf "%f\n") | cut -d'.' -f1 | sort
}
STEP=0
authenticate () {
printf "\e[0;104m"
sudo ls &> /dev/null
printf "\e[0m"
echonotice 'Authenticated.'
}
echostep $((++STEP))
authenticate
TABLE_COUNT=`get_tables | wc -l`
SPACE_AVAIL=`df -k --output=avail $(mysql_path) | tail -n1`
SPACE_NEEDED=(`sudo du -s $(old_db_path)`)
SPACE_ERR=`echo "$SPACE_AVAIL-$SPACE_NEEDED" | bc`
SPACE_WARN=`echo "$SPACE_AVAIL-$SPACE_NEEDED*3" | bc`
if [ $SPACE_ERR -lt 0 ]; then
echoerror 'There is not enough space to branch the database.'
echoerror 'Please free up some space and run this command again.'
SPACE_AVAIL_FORMATTED=`printf "%'d" $SPACE_AVAIL`
SPACE_NEEDED_FORMATTED=`printf "%'${#SPACE_AVAIL_FORMATTED}d" $SPACE_NEEDED`
echonotice "$SPACE_NEEDED_FORMATTED bytes needed to create database branch"
echonotice "$SPACE_AVAIL_FORMATTED bytes currently free"
exit 1
elif [ $SPACE_WARN -lt 0 ]; then
echowarn 'This action will use more than 1/3 of your available space.'
SPACE_AVAIL_FORMATTED=`printf "%'d" $SPACE_AVAIL`
SPACE_NEEDED_FORMATTED=`printf "%'${#SPACE_AVAIL_FORMATTED}d" $SPACE_NEEDED`
echonotice "$SPACE_NEEDED_FORMATTED bytes needed to create database branch"
echonotice "$SPACE_AVAIL_FORMATTED bytes currently free"
printf "\e[0;104m"
read -p " $(now): Do you still want to branch the database? [y/n] " -n 1 -r CONFIRM
printf "\e[0m"
echo
if [[ ! $CONFIRM =~ ^[Yy]$ ]]; then
echonotice 'Database was NOT branched'
exit 1
fi
fi
PASS='badpass'
connect_to_db () {
printf "\e[0;104m %s: MySQL root password: \e[0m" "$(now)"
read -s PASS
PASS=${PASS:-badpass}
echo
echonotice "Connecting to MySQL..."
}
create_db () {
echonotice 'Creating empty database...'
echo "CREATE DATABASE \`$NEW_DB\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci" | mysql -u root -p$PASS 2>> $(tmp_file 'errors.log')
DB_CREATED=true
}
build_tables () {
echonotice 'Retrieving and building database structure...'
mysqldump $OLD_DB --skip-comments -d -u root -p$PASS 2>> $(tmp_file 'errors.log') | pv --width 80 --name " $(now)" > $(tmp_file 'dump.sql')
pv --width 80 --name " $(now)" $(tmp_file 'dump.sql') | sql_on_new_db
}
set_debug_1 () {
echonotice 'Switching into recovery mode for innodb...'
printf '[mysqld]\ninnodb_file_per_table = 1\ninnodb_force_recovery = 1\n' | sudo tee $MYSQL_CNF_PATH > /dev/null
}
set_debug_0 () {
echonotice 'Switching out of recovery mode for innodb...'
sudo rm -f $MYSQL_CNF_PATH
}
discard_tablespace () {
echonotice 'Unlinking default data...'
(
echo "USE \`$NEW_DB\`;"
echo "SET foreign_key_checks = 0;"
get_tables | while read -r line;
do echo "ALTER TABLE \`$line\` DISCARD TABLESPACE; SELECT 'Table \`$line\` imported.';";
done
echo "SET foreign_key_checks = 1;"
) > $(tmp_file 'discard_tablespace.sql')
cat $(tmp_file 'discard_tablespace.sql') | sql_on_new_db | pv --width 80 --line-mode --size $TABLE_COUNT --name " $(now)" > /dev/null
}
import_tablespace () {
echonotice 'Linking imported data...'
(
echo "USE \`$NEW_DB\`;"
echo "SET foreign_key_checks = 0;"
get_tables | while read -r line;
do echo "ALTER TABLE \`$line\` IMPORT TABLESPACE; SELECT 'Table \`$line\` imported.';";
done
echo "SET foreign_key_checks = 1;"
) > $(tmp_file 'import_tablespace.sql')
cat $(tmp_file 'import_tablespace.sql') | sql_on_new_db | pv --width 80 --line-mode --size $TABLE_COUNT --name " $(now)" > /dev/null
}
stop_mysql () {
echonotice 'Stopping MySQL...'
sudo /etc/init.d/mysql stop >> $(tmp_file 'log')
}
start_mysql () {
echonotice 'Starting MySQL...'
sudo /etc/init.d/mysql start >> $(tmp_file 'log')
}
restart_mysql () {
echonotice 'Restarting MySQL...'
sudo /etc/init.d/mysql restart >> $(tmp_file 'log')
}
copy_data () {
echonotice 'Copying data...'
sudo rm -f $(new_db_path)*.ibd
sudo rsync -ah --info=progress2 $(old_db_path) --include '*.ibd' --exclude '*' $(new_db_path)
}
give_access () {
echonotice "Giving MySQL user \`$USER\` access to database \`$NEW_DB\`"
echo "GRANT ALL PRIVILEGES ON \`$NEW_DB\`.* to $USER@localhost" | sql_on_new_db
}
echostep $((++STEP))
connect_to_db
EXISTING_TABLE=`echo "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '$NEW_DB'" | mysql --skip-column-names -u root -p$PASS 2>> $(tmp_file 'errors.log')`
if [ "$EXISTING_TABLE" == "$NEW_DB" ]
then
echoerror "Database \`$NEW_DB\` already exists"
exit 1
fi
echoinstructions "The hamsters are working. Check back in 5-10 minutes."
sleep 5
echostep $((++STEP))
create_db
echostep $((++STEP))
build_tables
echostep $((++STEP))
set_debug_1
echostep $((++STEP))
discard_tablespace
echostep $((++STEP))
stop_mysql
echostep $((++STEP))
copy_data
echostep $((++STEP))
start_mysql
echostep $((++STEP))
import_tablespace
echostep $((++STEP))
set_debug_0
echostep $((++STEP))
restart_mysql
echostep $((++STEP))
give_access
echo
echosuccess "Database \`$NEW_DB\` is ready to use."
echo
trap general_cleanup EXIT
모든 것이 순조롭게 진행되면 다음과 같이 보일 것입니다.