我不确定这是否是正确的,但我记得读过,如果您正在对数据库进行读写,那么您是否在linux中运行以下命令

mysqldump -u username -p database_name > backup_db.sql


转储可能包含错误。

命令mysqldump中是否有特定选项来确保在实时系统上安全地完成此操作?我可以为用户禁用读/写几秒钟(数据库<50MB)

评论

哦...我希望有一个安全的方法,因为不仅转储中可能包含错误,而且如果在转储过程中发生了未保存的记录,数据库本身也不会得到未保存的记录。偶尔会发生这种情况,也许是在扫描相应的db表进行转储的同时保存了记录。因此,我担心在单个事务中进行备份,我想它会增加丢失记录的机会。

#1 楼

所有数据都是InnoDB
这将为您提供数据的准确时间点快照:
mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > backup_db.sql

--single-transaction产生一个检查点,该转储允许转储在捕获数据之前捕获所有数据。检查点,同时接收传入的更改。这些传入的更改不会成为转储的一部分。这样可以确保所有表的时间点相同。
--routines转储所有存储过程和存储函数
--triggers转储具有它们的每个表的所有触发器
所有数据都是MyISAM或Mix of InnoDB / MyISAM
您将必须强加全局读取锁,执行mysqldump并释放全局锁。
mysql -uuser -ppass -Ae"FLUSH TABLES WITH READ LOCK; SELECT SLEEP(86400)" &
sleep 5
mysql -uuser -ppass -ANe"SHOW PROCESSLIST" | grep "SELECT SLEEP(86400)" > /tmp/proclist.txt
SLEEP_ID=`cat /tmp/proclist.txt | awk '{print }'`
echo "KILL ${SLEEP_ID};" > /tmp/kill_sleep.sql
mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > backup_db.sql
mysql -uuser -ppass -A < /tmp/kill_sleep.sql

请尝试一下!
更新2012-06 -22 08:12 EDT
由于您的总数据少于50MB,因此我有另一种选择。与其在后台启动SLEEP命令以保持全局读取锁定86400秒(即24小时)只是为了获取进程ID并在外部杀死,我们不如尝试在mysql中而不是在OS中设置5秒超时:
SLEEP_TIMEOUT=5
SQLSTMT="FLUSH TABLES WITH READ LOCK; SELECT SLEEP(${SLEEP_TIMEOUT})"
mysql -uuser -ppass -Ae"${SQLSTMT}" &
mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > backup_db.sql

对于小型数据库,这是一种更干净,更简单的方法。

评论


5秒只是预防措施。您可以尝试使用较低的值。

– RolandoMySQLDBA
2012年6月20日下午3:33

Rolando-第1行中的错误2013(HY000)是在查询期间与MySQL服务器的连接丢失是否是预期的错误消息?

–user784637
2012年6月22日上午11:32

是否所有MySQL数据都在mysqldump中输出?

– RolandoMySQLDBA
2012年6月22日上午11:56

我不确定错误消息。这只是一个猜测,但这可能来自单行脚本,该脚本杀死了我在第二个脚本中提到的用户定义的SLEEP函数调用。

– RolandoMySQLDBA
2012年6月22日上午11:59

试试我的新建议,看看是否顺利。希望不会有错误消息。

– RolandoMySQLDBA
2012年6月22日12:16

#2 楼


对于InnoDB表,您应该使用--single-transaction选项,如另一个答案中所述。
对于MyISAM,有--lock-tables

在此处查看官方文档

#3 楼

如果要对MyISAM或混合表执行此操作,而又不会因锁定表而造成任何停机,则可以设置一个从数据库,并从那里获取快照。不幸的是,设置从属数据库会导致导出实时数据库的停机时间,但是一旦运行该数据库,您应该能够锁定它的表,并使用其他人描述的方法进行导出。发生这种情况时,它将落后于主服务器,但不会阻止主服务器更新其表,并且在备份完成后会立即赶上。

#4 楼

这是我的方法。由于使用FLUSH TABLES WITH READ LOCK,因此它在所有情况下均应工作。

#!/bin/bash

DB=example
DUMP_FILE=export.sql

# Lock the database and sleep in background task
mysql -uroot -proot $DB -e "FLUSH TABLES WITH READ LOCK; DO SLEEP(3600);" &
sleep 3

# Export the database while it is locked
mysqldump -uroot -proot --opt $DB > $DUMP_FILE

# When finished, kill the previous background task to unlock
kill $! 2>/dev/null
wait $! 2>/dev/null

echo "Finished export, and unlocked !"


shell sleep命令只是为了确保在运行mysqldump之前执行运行mysql lock命令的后台任务。您可以将其减少到1秒,但仍然可以。将其增加到30秒,然后尝试在30秒钟内将另一个客户端的任何表中的值插入,您会看到它已被锁定。

使用此手动背景锁定有两个优点,而不是使用mysqldump选项--single-transaction--lock-tables


如果您混合使用MyISAM / InnoDB表,则这将锁定所有内容。
在相同的锁定期间,除了mysqldump之外,您还可以运行其他命令。期。例如,在主节点上设置复制时,这很有用,因为您需要在创建的转储的确切状态(在解锁数据库之前)使用SHOW MASTER STATUS;获取二进制日志位置,以便能够创建复制从属。


#5 楼

mysql官方文档的建议是,您应该有一个Master“ M1”数据库和一个Slave“ S1”数据库,如“方案2:使用只读Slave进行备份”中所述,
备份Master或通过将其设置为只读进行从属

您应该将从属数据库设置为只读并执行

#6 楼

如果MYISAM表很大,并且需要不加锁转储该表并避免高服务器负载,则可以使用以下脚本。

#!/bin/sh

my_user="user"
my_password="password"
my_db="vpn"
my_table="traffic"
my_step=100000

read -p "Dumping table ${my_db}.${my_table} to ${my_table}.sql?" yn
case $yn in
    [Yy]* ) break;;
    * ) echo "User cancel."; exit;;
esac

my_count=$(mysql $my_db -u $my_user -p$my_password -se "SELECT count(*) FROM $my_table")
my_count=$(($my_count + 0))

if [ ! $my_count ]
then
    echo "No records found"
    exit
fi

echo "Records in table ${my_db}.${my_table}: ${my_count}"

echo "" > $my_table.sql

max_progress=60

for (( limit=0; limit<=$my_count; limit+=$my_step )); do
    progress=$((max_progress * ( limit + my_step) / my_count))

    echo -ne "Dumping ["
    for ((i=0; i<$progress; i ++)); do
        echo -ne "#"
    done
    for ((; i<$max_progress; i ++)); do
        echo -ne "."
    done

    mysqldump -u $my_user -p$my_password --complete-insert --no-create-info --opt --where="1 limit $limit , $my_step" $my_db $my_table >> $my_table.sql
    echo "" >> $my_table.sql

    echo -ne "] $((100 * ( limit + my_step ) / my_count)) %"
    echo -ne "\r"

    sleep 1

done

echo -ne "\n"