Mysql

使用 mysql 中的 keycache 修復每次都會執行。甚至無法記錄它發生的原因

  • September 8, 2017

我有一個 MyISAM 表,其中包含約 100 萬行和兩個索引——一個是三列鍵,另一個是單獨點列上的有界 SELECT 語句的空間索引。我的插入語句通常將十進制度插入“緯度”和“長”列,更新觸發器將這些轉換並插入到點列中以便更快地讀取。

問題是,每次我從增量 mysqldump 執行(小)批量插入時,伺服器都會進入“使用 keycache 修復”模式,並且需要大約 20 分鐘才能完成插入大約 1,000 行!

誠然,我在一台極小的機器上(AWS Micro 實例,最多 2 個核心和 ~600megs 記憶體),但它仍然不應該使用“使用 keycache 修復”。我已經在Google上搜尋了幾個小時並進行了調整和刺激設置和理論,但沒有運氣。我能找到的一切都表明它與最大理論索引大小有關,但即使將 myisam_max_sort_file_size 設置為 ~1TB 也不起作用。我什至無法弄清楚如何打開足夠精細的日誌記錄以查看可能導致問題的原因。

我的.conf:

[mysqld]
datadir=/var/lib/mysql
tmpdir=/var/lib/mysql/tmp
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
skip-external-locking
long_query_time=3
slow_query_log
slow_query_log_file=/var/log/log-slow-queries.log
log-bin=mysql-bin
log-error=/var/log/mysqld.log
log-warnings=5
server-id= 1
myisam_max_sort_file_size=900G
myisam_sort_buffer_size=300M
myisam_repair_threads=1
skip-innodb
key_buffer_size=128M
bulk_insert_buffer_size=512M


[mysqld_safe]
log-error=/var/log/mysqld_safe.log
pid-file=/var/run/mysqld/mysqld.pid
myisam_recover_options

日誌文件中的一個塊:

120410 06:15:57 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended
120410 06:15:58 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql
120410  6:15:58 [Note] Plugin 'InnoDB' is disabled.
120410  6:15:59 [Note] Event Scheduler: Loaded 0 events
120410  6:15:59 [Note] /usr/libexec/mysqld: ready for connections.
Version: '5.1.61-log'  socket: '/var/lib/mysql/mysql.sock'  port: 3306  Source distribution
120410  7:06:57 [Note] /usr/libexec/mysqld: Normal shutdown

120410  7:06:57 [Note] Event Scheduler: Purging the queue. 0 events
120410  7:06:57 [Note] /usr/libexec/mysqld: Shutdown complete

120410 07:06:57 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended
120410 07:06:58 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql
120410  7:06:58 [Note] Plugin 'InnoDB' is disabled.
120410  7:06:58 [Note] Event Scheduler: Loaded 0 events
120410  7:06:58 [Note] /usr/libexec/mysqld: ready for connections.
Version: '5.1.61-log'  socket: '/var/lib/mysql/mysql.sock'  port: 3306  Source distribution
120410  7:26:57 [Note] /usr/libexec/mysqld: Normal shutdown

120410  7:26:57 [Note] Event Scheduler: Purging the queue. 0 events
120410  7:26:57 [Note] /usr/libexec/mysqld: Shutdown complete

120410 07:26:57 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended

有問題的 SHOW CREATE TABLE:

CREATE TABLE `production_objects_0` (
 `objId` int(11) NOT NULL AUTO_INCREMENT,
 `col2` tinyint(1) DEFAULT NULL,
 `col3` varchar(200) DEFAULT NULL,
 `col1` int(32) DEFAULT NULL,
 `Lat` double DEFAULT NULL,
 `Long` double DEFAULT NULL,
 `lat_long_point` point NOT NULL,
 PRIMARY KEY (`objId`),
 SPATIAL KEY `point_index` (`lat_long_point`),
 KEY `name_index` (`col1`,`col2`,`col3`)
) ENGINE=MyISAM AUTO_INCREMENT=1081735 DEFAULT CHARSET=utf8 PACK_KEYS=1 

我正在使用由 mysqldump 創建的標準插入語句,唯一可能不尋常的是我將此觸發器應用於表:

CREATE TRIGGER set_lat_long_point 
     BEFORE INSERT ON production_objects_0 FOR EACH ROW 
     SET  new.lat_long_point = GeomFromText(concat('Point(',new.Long,' ',new.Lat,')'));

df -h 輸出:

Filesystem            Size  Used Avail Use% Mounted on
/dev/xvda1           1009G  6.0G  992G   1% /
tmpfs                 298M     0  298M   0% /dev/shm
(ls -l shows that user mysql owns everything, including the tmp dir, in /var/lib/mysql)

關於可能導致伺服器完全忽略排序修復的任何想法?我的觸發器有可能以某種方式引起事情嗎?在最新版本的 MySQL 上,空間索引甚至可以與“排序修復”一起使用嗎?我讀到在過去的版本中存在問題,但最近的東西(我在 5.1 上)沒有(好或壞)。

關於如何註銷/退出/觀看正在發生的事情以便我可以繼續進行分類的想法也會有所幫助。


Rolando 的密鑰緩衝區推薦查詢建議我的伺服器大小為 76M,因此我將其設置為 128M,並bulk_insert_buffer_size根據 Rolando 的建議添加了 512M。我還將伺服器的磁碟大小增加到 1TB 並將其提升myisam_max_sort_file_size到 900G,以確保這不是罪魁禍首,並且它仍在使用“從 keycache 修復”從插入中恢復。

我的觸發器有可能以某種方式引起事情嗎?在最新版本的 MySQL 上,空間索引甚至可以與“排序修復”一起使用嗎?我讀到在過去的版本中存在問題,但最近的東西沒有(好或壞)(我在 5.1 上)。

我將伺服器(當然很小)的 8GB 磁碟升級為 100GB 磁碟。執行df -h顯示與臨時目錄相同的文件系統上有 92GB 可用空間,而表約為 500MB。我的 ~90GB 磁碟空間是否仍然太小?

您的 my.conf 內容如下:key_buffer_size=32M這真的很小。您可以將其設置得更高:請執行此查詢:

SELECT CONCAT(ROUND(KBS/POWER(1024,
IF(PowerOf1024<0,0,IF(PowerOf1024>3,0,PowerOf1024)))+0.4999),
SUBSTR(' KMG',IF(PowerOf1024<0,0,
IF(PowerOf1024>3,0,PowerOf1024))+1,1))
recommended_key_buffer_size FROM
(SELECT LEAST(POWER(2,32),KBS1) KBS
FROM (SELECT SUM(index_length) KBS1
FROM information_schema.tables
WHERE engine='MyISAM' AND
table_schema NOT IN ('information_schema','mysql')) AA ) A,
(SELECT 2 PowerOf1024) B;

這將為您提供推薦的 key_buffe_size 大小。請在設置此值時使用常識。

這是別的東西:我沒有看到bulk_insert_buffer_size。預設值為 8MB。嘗試將其設置為 512MB:

[mysqld]
bulk_insert_buffer_size=512M

我剛剛注意到你的myisam_sort_buffer_size只有 300M。將其設置為 4G(最大值)

[mysqld]
myisam_sort_buffer_size=4G

引用自:https://dba.stackexchange.com/questions/16296