2012-12-27 61 views
9

Tôi viết một kịch bản lệnh sao lưu để thực thi mysqldump.Làm thế nào để khóa tất cả các bảng trong một db mysql?

mysqldump -u$BACKUP_USER -p$BACKUP_PASS --flush-logs --lock-tables $DB_NAME > $SQL_FILE 

Công cụ lưu trữ của tôi là MyISAM. Vì vậy, tôi không thể sử dụng tùy chọn --single-transaction. --lock-tables chỉ khóa một bảng trong tiến trình mysqldump. Có nhiều cơ sở dữ liệu trong cá thể MySQL của tôi, tôi không muốn sử dụng --lock-all-tables, nó sẽ khóa tất cả các cơ sở dữ liệu chạy trong máy chủ của tôi. Vì vậy, Làm thế nào để khóa tất cả các bảng trong ONE cơ sở dữ liệu mysql tại sametime vì vậy tôi có thể đổ nó?

+1

'--lock-tables' nên khóa tất cả các bảng được bán trước khi bán chúng. Điều gì làm cho bạn nghĩ rằng nó không làm như vậy? – cdhowie

+0

Tôi có thử nghiệm trong mysql 5.1, khi tôi sử dụng --lock-tables trong mysqldump, tôi vẫn có thể chèn dữ liệu vào bảng cơ sở dữ liệu $ DB_NAME. – KeepZero

Trả lời

4

Bạn nên xem xét tùy chọn này.

FLUSH TABLES WITH READ LOCK

Đóng tất cả các bảng mở và khóa tất cả các bảng cho tất cả các cơ sở dữ liệu với một khóa đọc toàn cầu. Đây là một cách rất thuận tiện để có được bản sao lưu ...

http://dev.mysql.com/doc/refman/5.0/en/flush.html

+0

'FLUSH TABLES VỚI READ LOCK' – Benjamin

+0

Điều này phát ra khóa đọc * toàn cầu *, không chỉ các bảng trong một cơ sở dữ liệu duy nhất. –

6

Không phải là giải pháp đẹp nhất cho đến nay, nhưng công trình này. Tôi đã có nhu cầu tương tự và đây là giải pháp của tôi, hơi sửa đổi để phù hợp với tên biến của bạn. Tôi giả sử bạn đang chạy MySQL trên Linux, vì điều này phụ thuộc khá nhiều vào ngữ nghĩa shell BASH. Nếu bạn đang sử dụng Windows, điều này có thể sẽ không hoạt động.

# Mysql script to lock all tables in one DB 
# (such as to get a consistent export dump of one database) 

MYSQLCMD="mysql -u$BACKUP_USER -p$BACKUP_PASS -A" 

function lock_db { 
    [ -e "/tmp/mysql-db-lock-${1}" ] && rm "/tmp/mysql-db-lock-${1}" 
    mkfifo "/tmp/mysql-db-lock-${1}" 
    (
    (
     echo "SELECT CONCAT('LOCK TABLES ' 
      , GROUP_CONCAT(CONCAT('\`',table_name,'\`'),' WRITE') 
      , ';' 
      ) AS \"-- Statement to lock tables\" 
     FROM information_schema.tables 
     WHERE table_schema='${1}' 
     ORDER BY table_name; 
     " | $MYSQLCMD 
     echo "\! cat '/tmp/mysql-db-lock-${1}' >/dev/null" 
     echo 'UNLOCK TABLES;' 
    ) | $MYSQLCMD -D"${1}" 
    rm "/tmp/mysql-db-lock-${1}" 
) & 
} 

function unlock_db { 
    >"/tmp/mysql-db-lock-${1}" 
} 

# Lock one database, all tables 
lock_db $DB_NAME 

# Verify locks have been placed 
echo "SHOW OPEN TABLES WHERE in_use != 0" | $MYSQLCMD 

# Do whatever here that you needed the locked db for 
mysqldump -u$BACKUP_USER -p$BACKUP_PASS $DB_NAME > $SQL_FILE 

# Release locks 
unlock_db $DB_NAME 

# Verify locks released 
echo "SHOW OPEN TABLES WHERE in_use != 0" | $MYSQLCMD 
+0

Bạn chọn từng bảng trong cơ sở dữ liệu. Điều này có thể tốt hơn "FLUSH TABLES WITH READ LOCK" khóa tất cả các bảng trong tất cả các cơ sở dữ liệu nhưng giải pháp của bạn dường như không thành công với cơ sở dữ liệu chứa nhiều bảng (ít nhất là đối với tôi). Tôi đã thay đổi nó bằng cách sử dụng "FLUSH TABLES WITH READ LOCK" (khóa tất cả các bảng trên tất cả các cơ sở dữ liệu) và loại bỏ đường ống đầu tiên thành $ MYSQLCMD. – OderWat

+0

CẬP NHẬT: Tôi đã sử dụng "SET SESSION group_concat_max_len = 8192;" trước ECHO đầu tiên của bạn vì đó là nguyên nhân gây ra vấn đề ngay từ đầu! TY cho bạn kịch bản mát mẻ! – OderWat

+0

Vui lòng upvote nếu bạn thích. –

2

Đây là cách tôi đã làm. Nó sẽ hoạt động trong mọi trường hợp vì nó sử dụng 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 !" 

Vỏ sleep lệnh chỉ là để đảm bảo rằng các nhiệm vụ nền chạy mysql khóa lệnh được thực thi trước khi mysqldump bắt đầu. Bạn có thể giảm xuống còn 1 giây và nó vẫn ổn. Tăng tốc độ này lên 30 giây và thử chèn một giá trị vào bất kỳ bảng nào từ ứng dụng khách khác trong 30 giây đó, bạn sẽ thấy giá trị đó bị khóa.

Có 2 lợi thế trong việc sử dụng nền khóa hướng dẫn này, thay vì sử dụng các tùy chọn mysqldump--single-transaction--lock-tables:

  1. này khóa tất cả mọi thứ, nếu bạn đã trộn bảng MyISAM/InnoDB.
  2. Bạn có thể thực hiện các lệnh khác ngoài mysqldump trong cùng thời gian khóa. Nó hữu ích, ví dụ, khi thiết lập nhân rộng trên một nút chính, bởi vì bạn cần phải có được vị trí đăng nhập nhị phân với SHOW MASTER STATUS; ở trạng thái chính xác của kết xuất bạn đã tạo (trước khi mở khóa cơ sở dữ liệu), để có thể tạo một bản sao nô lệ .
+0

Điều này cũng phát hành khóa * toàn cầu * trên tất cả các cơ sở dữ liệu, ngay cả khi bạn đang sao lưu một cơ sở dữ liệu duy nhất. –

Các vấn đề liên quan