MySQL treo hoàn toàn khi `ALTER TABLE [ENABLE KEY`


7

Tôi biết rất ít về quản trị cơ sở dữ liệu nhưng tôi phải xử lý một số bảng rất lớn trên trang web của mình.

Máy chủ này có 64GB RAM và Intel Core i7-3820 (4 x 3600 MHz). Hầu hết mọi thứ nó làm là MySQL. Tôi sử dụng một nửa bảng MyISAM và một nửa bảng InnoDB.

Tôi có một vài bảng trong MyISAM với hàng tỷ hàng. Mỗi ngày tôi có một tập lệnh vô hiệu hóa các khóa, thêm một vài triệu hàng, sau đó bật lại các khóa. Các ALTER TABLE... ENABLE KEYSnguyên nhân cơ bản để máy chủ dừng lại trong một vài giờ. Không có trang web nào sử dụng MySQL sẽ tải cả, mặc dù chúng không truy cập vào các bảng bị thay đổi.

Ngoài ra, vui lòng tư vấn cho tôi cách thiết lập tệp my.cnf để khắc phục sự cố này và tối ưu hóa để xây dựng lại các chỉ mục này nhanh nhất có thể. Ai đó bảo tôi tăng key_buffer_size, nhưng tôi không chắc liệu điều này có tốt không vì mọi người dường như có ý kiến ​​khác nhau ..? Hiện tại nó trông như thế này:

[client]
port        = 3306
socket      = /var/lib/mysql/mysql.sock

[mysqld]
port = 3306
socket = /var/lib/mysql/mysql.sock
skip-external-locking
max_allowed_packet = 512M
table_open_cache = 1024
sort_buffer_size = 128M
read_buffer_size = 2M
read_rnd_buffer_size = 8M
myisam_sort_buffer_size = 24G
thread_cache_size = 12
query_cache_size = 256M
thread_concurrency = 16
log-bin=mysql-bin
binlog_format=mixed
server-id   = 1
innodb_file_per_table = 1
table_cache = 1024
key_buffer = 256M
key_buffer_size = 12G
myisam_repair_threads = 4
big-tables
bind-address = 127.0.0.1
max_connections = 400
tmp_table_size = 4G
max_heap_table_size = 4G
log_bin = /backup/mysql-bin-logs/mysql-bin.log
expire_logs_days        = 10
max_binlog_size         = 100M
innodb_buffer_pool_size = 12G
local-infile=1
net_read_timeout = 1800
net_write_timeout = 1800


[mysqldump]
quick
max_allowed_packet = 16M

[mysql]
no-auto-rehash
local-infile=1

[myisamchk]
key_buffer_size = 256M
sort_buffer_size = 256M
read_buffer = 2M
write_buffer = 2M
key_buffer = 256M

[mysqlhotcopy]
interactive-timeout

Phiên bản MySQL

innodb_version 5.5.30
protocol_version 10
version 5.5.30-log
version_comment MySQL Community Server (GPL) by Remi
version_compile_machine x86_64
version_compile_os Linux

CẬP NHẬT

Tôi đã bắt đầu một tiền thưởng. Tôi đã thay đổi một số cài đặt my.conf (cũng được cập nhật trong bài viết này). Sau đó, khi tôi cố gắng xây dựng lại các chỉ mục trên bảng lớn, nó bắt đầu với Repair with 8 threads(mặc dù số lượng luồng sửa chữa được đặt là 4) và sau đó khi tôi kiểm tra nó vài giờ sau đó, lệnh tương tự đã được bật Repair with keycache, bây giờ nó đã ở đó ngồi. Vì vậy, bằng cách nào đó, nó đã xuống cấp từ phương pháp sắp xếp sang keycache (tôi không biết tại sao!)

Xin hãy giúp tôi tối ưu hóa điều này! Nó được cho là chạy mỗi ngày nhưng hiện tại chỉ mất vài ngày ALTER TABLE... ENABLE KEYS.

Dưới đây là một số biến khác tôi đã được yêu cầu, điều mà tôi không hiểu nhưng có thể giúp bạn giúp tôi:

+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| key_cache_block_size | 1024  |
+----------------------+-------+
+-----------------+-------------+
| Variable_name   | Value       |
+-----------------+-------------+
| key_buffer_size | 12884901888 |
+-----------------+-------------+
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Key_blocks_unused | 0     |
+-------------------+-------+

CẬP NHẬT 2 (21/21)

Nghĩ rằng nó sẽ giải quyết vấn đề cho tôi, tôi đã thay đổi tập lệnh của mình để cắt hoàn toàn bảng, đặt lại tất cả các hàng và thêm các chỉ mục một lần. Thay vì vô hiệu hóa khóa, thêm hàng mới và sau đó bật khóa.

Thật không may, nó không giúp được gì vì việc tạo chỉ mục vẫn còn repair with keycache.

Đây là kết quả của SHOW CREATE TABLE research_storage1:

CREATE TABLE `research_storage1` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `word1` mediumint(8) unsigned NOT NULL,
  `word2` mediumint(8) unsigned NOT NULL,
  `origyear` smallint(5) unsigned NOT NULL,
  `cat` tinyint(3) unsigned NOT NULL,
  `pibn` int(10) unsigned NOT NULL,
  `page` smallint(5) unsigned NOT NULL,
  `pos` smallint(5) unsigned NOT NULL,
  `num` tinyint(3) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `pibnpage` (`pibn`,`page`,`word2`,`word1`),
  KEY `word21pibn` (`word2`,`word1`,`pibn`,`num`),
  KEY `word12num` (`word1`,`word2`,`num`),
  KEY `cat1` (`cat`,`word1`),
  KEY `year1` (`origyear`,`word1`),
  KEY `catyear1` (`cat`,`origyear`,`word1`),
  KEY `pibn` (`pibn`,`word1`)
) ENGINE=MyISAM DEFAULT CHARSET=ascii COLLATE=ascii_bin DATA DIRECTORY='/storage/researchdb/' INDEX DIRECTORY='/storage/researchdb/';

Tôi cũng đã chạy lệnh này: SELECT data_length/power(1024,3) dat,index_length/power(1024,3) ndx FROM information_schema.tables WHERE table_schema='dbname' AND table_name='tablename'; Nhưng vấn đề với điều này là tôi hiện có 2 bảng cho bảng này, 1 bảng bị cắt và 1 có tất cả dữ liệu nhưng không có chỉ mục (bảng trước sẽ được thay thế bằng bảng sau khi chỉ mục hoàn thành ) ... lý do là vì tôi không thể xây dựng các chỉ số chết tiệt (do đó có vấn đề). Đây là thông tin cho bảng rút gọn, và sau đó là bảng có dữ liệu nhưng không có chỉ mục:

+------+------------------------+
| dat  | ndx                    |
+------+------------------------+
|    0 | 0.00000095367431640625 |
+------+------------------------+
+-------------------+--------------------+
| dat               | ndx                |
+-------------------+--------------------+
| 51.61232269741595 | 27.559160232543945 |
+-------------------+--------------------+

Cũng xin lưu ý rằng bảng sẽ lớn hơn gấp 10 lần so với trước khi tất cả dữ liệu được nhận.


Bạn có thể chia sẻ phiên bản chính xác của mysql mà bạn đang sử dụng ( show variables like '%version%';) không? Một số phiên bản khá cũ có lỗi lớn với các phím ENABLE. Ngoài ra còn có một số thông tin về việc tạo chỉ mục ở đây có thể giúp ích.
Nathan Jolly

OK, tôi đã chỉnh sửa bài viết với nó.
Alasdair

Lần tới khi bạn ALTER TABLE ... ENABLE KEYSchạy, vui lòng chạy SHOW PROCESSLIST;và chỉ đăng kết quả đầu ra của Quá trình đó.
RolandoMySQLDBA

Bạn có thể gửi kết quả của những điều khoản sau đây ( SHOW VARIABLES LIKE 'key_cache_block_size';, SHOW VARIABLES LIKE 'key_buffer_size';, SHOW GLOBAL STATUS LIKE '%Key_blocks_unused%'; )?
Cristian Porta

Tôi đã cập nhật bài viết chính với mới nhất.
Alasdair

Câu trả lời:


3

Ngay bây giờ, bạn đang ở một vị trí rất may mắn. Tôi nhận thấy bạn đã big-tablesxác định. Điều này ngăn bạn gặp lỗi "Bảng là đầy đủ". Tại sao điều này là tốt?

Bất cứ khi nào bạn nhận được "Sửa chữa với Keycache" làm trạng thái, bạn không có không gian trống để thực hiện sắp xếp tệp. Làm cho sort_buffer_size lớn hơn không nhất thiết phải là câu trả lời vì các bảng tạm thời trở thành tệp đĩa ngay lập tức.

Bạn có hai lựa chọn

TÙY CHỌN # 1: Tăng không gian đĩa cho datadir

Khối lượng dữ liệu trong đó /var/lib/mysql(hoặc bất cứ thứ gì datadir) nằm có thể không đủ chỗ để chứa một bảng tạm thời được vật chất hóa trên đĩa. Tôi sẽ đề nghị tăng kích thước của ổ đĩa, ít nhất là gấp đôi kích thước của nó.

DRAWBACK : Bảo trì một lần để di chuyển cơ sở dữ liệu sang đĩa lớn hơn.

TÙY CHỌN # 2: Đĩa riêng cho Bàn Temp

Có lẽ có một khối lượng đĩa riêng biệt, mục đích duy nhất trong cuộc sống là đặt các bảng tạm thời nên được thiết lập. Thử cái này

  • Bước 01: Cài đặt đĩa có cùng kích thước với nhà của datadir
  • Bước 02: mkdir /tmptables
  • Bước 03: Gắn ổ đĩa mới vào thư mục /tmptables
  • Bước 04: chown mysql:mysql /tmptables
  • Bước 05: Thêm cái này vào my.cnf
    • tmpdir=/tmptables
  • Bước 06: service mysql restart

Một khi bạn tạo đĩa và thêm tmpdir, bạn nên có nhiều phòng khuỷu tay.

DRAWBACK : Chuyển nội dung của bảng tạm thời từ /tmptablestrở về nhà của datadirmột số lệnh SQL nhất định (chẳng hạn như DDL).

CẬP NHẬT 2013-05-21 00:10 EDT

Bạn chỉ đơn giản là không có đủ bộ nhớ. Tất cả các lõi trên thế giới không thể giúp MyISAM.

SUGGESTION # 1: Rút ngắn chìa khóa của bạn

Tôi có thể nói từ các khóa mà bạn đang cố lấy tất cả dữ liệu từ các chỉ mục và tránh chạm vào bảng. Tất cả đều tốt và tốt NẾU KHÔNG PHẢI LÀ CHO HÓA ĐƠN CỦA ROWS.

Đây là một điều đáng để xem xét: Rút ngắn các khóa cho mỗi chỉ mục

CREATE TABLE `research_storage1` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `word1` mediumint(8) unsigned NOT NULL,
  `word2` mediumint(8) unsigned NOT NULL,
  `origyear` smallint(5) unsigned NOT NULL,
  `cat` tinyint(3) unsigned NOT NULL,
  `pibn` int(10) unsigned NOT NULL,
  `page` smallint(5) unsigned NOT NULL,
  `pos` smallint(5) unsigned NOT NULL,
  `num` tinyint(3) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `pibnpage` (`pibn`,`page`),
  KEY `word21` (`word2`,`word1`),
  KEY `cat1` (`cat`,`word1`),
  KEY `year1` (`origyear`,`word1`),
  KEY `catyear1` (`cat`,`origyear`),
  KEY `pibn` (`pibn`,`word1`)
) ENGINE=MyISAM DEFAULT CHARSET=ascii COLLATE=ascii_bin
DATA DIRECTORY='/storage/researchdb/'
INDEX DIRECTORY='/storage/researchdb/';

SUGGESTION # 2: Ngừng sử dụng ALTER TABLE...ENABLE KEYS;

Bạn nên cố gắng đưa MyISAM được nhập vào một bảng mới mà không cần sử dụng ENABLE KEYS.

CREATE TABLE `research_storagenew` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `word1` mediumint(8) unsigned NOT NULL,
  `word2` mediumint(8) unsigned NOT NULL,
  `origyear` smallint(5) unsigned NOT NULL,
  `cat` tinyint(3) unsigned NOT NULL,
  `pibn` int(10) unsigned NOT NULL,
  `page` smallint(5) unsigned NOT NULL,
  `pos` smallint(5) unsigned NOT NULL,
  `num` tinyint(3) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `pibnpage` (`pibn`,`page`,`word2`,`word1`),
  KEY `word21pibn` (`word2`,`word1`,`pibn`,`num`),
  KEY `word12num` (`word1`,`word2`,`num`),
  KEY `cat1` (`cat`,`word1`),
  KEY `year1` (`origyear`,`word1`),
  KEY `catyear1` (`cat`,`origyear`,`word1`),
  KEY `pibn` (`pibn`,`word1`)
) ENGINE=MyISAM DEFAULT CHARSET=ascii COLLATE=ascii_bin
DATA DIRECTORY='/storage/researchdb/'
INDEX DIRECTORY='/storage/researchdb/';
INSERT INTO `research_storagenew` SELECT * FROM `research_storage1`;
DROP TABLE `research_storage1`;
ALTER TABLE `research_storagenew` RENAME `research_storage1`;

TÓM LƯỢC

Nhìn vào định nghĩa bảng một lần nữa. Có 18 byte cho một mục chỉ mục trên chỉ pibnpagemục. Đó là 18G mỗi tỷ hàng. Cùng đi với word21pibn. Bạn không có đủ phòng. Bắt buộc phải thử một trong những gợi ý mới nhất của tôi để bỏ qua nhu cầu sắp xếp tất cả các khóa này.

CẬP NHẬT 2013-05-22 12:15 EDT

Bạn đã hỏi

Về việc rút ngắn các phím mặc dù: loại hiệu suất này sẽ dẫn đến kết quả gì? Có phải chúng ta đang nói chuyện dài gấp đôi, dài gấp 10 lần, dài gấp 1000 lần?

Tôi không thể nói chắc chắn những gì thời gian chạy sẽ có tác động. Tuy nhiên, tôi có thể nói điều này: Có thể có một số I / O đĩa bổ sung vì các chỉ mục sẽ không còn chứa thông tin cột cần thiết. Các truy vấn sẽ không phải chuyển sang .MYDtệp để lấy thông tin cột bổ sung. Xin lưu ý rằng MyISAM phù hợp với các truy vấn đọc nhiều.

Điều chỉnh duy nhất tôi có thể khuyến nghị thêm nếu có nghĩa là CHỨNG MINH và XÓA vào giữa ngày trong thời gian đọc nặng sẽ là bật INSERT đồng thời.

[mysqld]
concurrent_insert=1

Điều này sẽ cho phép INSERT vào MyISAM mà không cần kiểm tra chéo các khối miễn phí trong bảng. Điều này có thể làm cho bảng phát triển nhanh hơn một chút.

Theo như bảo trì, bạn phải sử dụng SUGGESTION #2như không phụ thuộc quá nhiều vào ALTER TABLE ... ENABLE KEYS;bảng cồng kềnh như vậy. Có lẽ bạn nên nghĩ đến việc chuyển /storage/researchdb/sang SSD.


Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
Paul White 9
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.