首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

FreeBSD 編譯 MySQL 卡在 sql_yacc.cc 解決方案:低內存編譯優化與 ports 機制解析

     編輯:MySQL 資料庫相關知識

現象:編譯無限卡住或報錯

  • 現象 A:sql/sql_yacc.cc 編譯階段運行數小時無進展,CPU 佔用低,內存佔用極高。
  • 現象 B:報錯 Internal compiler error: program cc1plus got fatal signal 11 / Out of virtual memory / virtual memory exhausted。

根因:Bison 生成的龐大解析器 + GCC 模板實例化爆炸

sql_yacc.cc 是由 Bison 從 sql_yacc.yy 生成的 C++ 解析器代碼,包含極其龐大的 switch-case 狀態機、大量內聯函數、模板實例化。GCC 編譯此文件時:

  • 默認開啟 -finline-functions、-O2 優化,嘗試內聯海量函數 → 符號表爆炸、內存指數增長。
  • 模板元編程 (MySQL 解析器大量使用) 在編譯期展開 → 編譯器內存需求遠超源代碼大小。
  • FreeBSD 基礎系統 GCC 版本較舊 (4.x/5.x 早期),內存管理不如新版高效。

三種解決方案 (按推薦度排序)

方案 1:啟用低內存編譯模式 (官方推薦,最快)


./configure --with-low-memory
# 或
CXXFLAGS="-fno-inline -O0" ./configure
make
  • --with-low-memory 自動注入 -fno-inline (GCC) 或 -O0 (其他編譯器),禁用內聯、關閉優化,劇減編譯內存峰值。
  • 編譯時間從「數小時/失敗」降至「數分鐘」。
  • 生成的二進制性能略有下降 (僅影響解析器模塊),運行時無感知。

方案 2:使用 Ports 系統安裝 (FreeBSD 原生包管理)


cd /usr/ports/databases/mysql80-server  # 或 mysql57-server 等
make config  # 選擇所需選項
make install clean
  • Ports Makefile 內建 -O0 / -fno-inline 補丁針對 sql_yacc.cc。
  • 自動處理依賴 (libtool、cmake、openssl 等)、編譯參數優化、啟動腳本、日誌輪轉。
  • 升級/卸載/選項調整統一管理,生產環境首選。

方案 3:增加交換空間 / 物理內存 (治標不治本)


# 臨時增加 4GB Swap
dd if=/dev/zero of=/swapfile bs=1M count=4096
mkswap /swapfile
swapon /swapfile
# 編譯完成後可關閉
swapoff /swapfile
rm /swapfile
  • 僅緩解內存不足,編譯時間仍極長 (內存壓力大時頻繁 Swap)。
  • 不建議作為常規手段。

Ports 機制深度解析:為什麼它能自動搞定?


# /usr/ports/databases/mysql80-server/Makefile 片段
.if ${COMPILER_TYPE} == clang || ${COMPILER_TYPE} == gcc
CXXFLAGS+=	-fno-inline-functions
.endif

# 針對 sql_yacc.cc 的特殊處理
post-patch:
	@${REINPLACE_CMD} -e 's|-O2|-O0|' ${WRKSRC}/sql/CMakeLists.txt
  • Ports 維護者已將針對性編譯參數補丁內建到 Ports 樹中。
  • libtool 依賴:libtool 是 GNU 構建系統膠水層,統一共享庫構建接口,Ports 自動拉取構建依賴,非運行時依賴。
  • pkg install mysql80-server 直接拿預編譯二進制包,完全跳過編譯,最省時。

現代 FreeBSD (12/13/14) + Clang/LLVM 環境

  • 基礎編譯器已切換為 Clang,內存管理優於舊 GCC。
  • Clang 默認較保守內聯策略,sql_yacc.cc 編譯通常無需特殊參數即可通過。
  • 若仍遇內存問題:CXXFLAGS="-fno-inline" make 即可。

避坑清單

  1. ❌ 直接 make -j$(nproc) 全速並行編譯 → 內存峰值 × 核心數,必發 OOM。編譯 sql_yacc.cc 時建議單線程:make -j1 sql/sql_yacc.cc.obj 再 make -j$(nproc)。
  2. ❌ 忽略 --with-low-memory 文檔提示 → 浪費數小時等待失敗。
  3. ❌ 手動修改 CMakeLists.txt / Makefile 硬編碼參數 → 升級時遺失,Ports 機制失效。
  4. ✅ 生產環境直接 pkg install 或 portmaster databases/mysql80-server,除非需要極度定制編譯選項。

FreeBSD 編譯 MySQL 卡在 sql_yacc.cc 是經典的「編譯器內存爆炸」案例。**理解根因 (Bison 生成代碼特性 + GCC 內聯優化),應用官方 --with-low-memory 或 Ports 內建優化,能將編譯時間從「不可接受」壓縮到「喝杯咖啡的功夫」**。現代 FreeBSD + Clang 環境下該問題已大幅緩解,但掌握排查思路對所有大型 C++ 專案編譯優化皆有裨益。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved