2012-07-05 96 views
2

我遇到了一個煩人的問題。內存不足MySQL與24GB服務器

我已經做了系統,現在的用戶告訴我,這是給他們的信息:

超出內存(所需268435427個字節)

整個數據庫的大小是12MB和查詢有問題已經運行好幾個月,並不是那麼複雜或很大。

該數據庫是innodb。我的服務器有24GB的內存,所以我嚴重懷疑它實際上是內存不足。

的my.cnf如下:

的key_buffer = 8000M

max_allowed_pa​​cket的= 1M

的table_cache = 2048M

sort_buffer_size的值= 1M

的net_buffer_length = 1024M

read_buffer_size = 1M

read_rnd_buffer_size = 24M

innodb_log_file_size = 5M

innodb_log_buffer_size = 8M

的innodb_flush_log_at_trx_commit = 1

innodb_lock_wait_timeout = 50

innodb_buffer_pool_size = 1024M

innodb_additional_mem_pool_size = 2M

MAX_CONNECTIONS = 100

query_cache_size變量= 128M

query_cache_min_res_unit變量= 1024

query_cache_limit = 16MB

thread_cache_size的= 100

max_heap_table_size = 4096MB

在Windows任務管理器中查看時,我看到18.8GB可用,但只有100MB空閒。這是Windows 2008 64位服務器,這可能是問題的根源嗎?


下面是該查詢:

$currency  = '(SELECT currencies.symbol 
          FROM parts_trading, currencies 
          WHERE parts_trading.enquiryRef = enquiries.id 
          AND parts_trading.sellingCurrency = currencies.id 
          LIMIT 1 
         )' ; 

$amountDueSQL = '(
         (SELECT SUM(quantity*(parts_trading.sellingNet 
            + 
            parts_trading.sellingVat)) 
          FROM parts_trading 
          WHERE parts_trading.enquiryRef = enquiries.id 
         ) 
         + 
         (SELECT SUM(enquiries_custom_fees.feeAmountNet 
            + 
            enquiries_custom_fees.feeAmountVat) 
          FROM enquiries_custom_fees 
          WHERE enquiries_custom_fees.enquiryRef = enquiries.id 
         ) 
         )' ; 
$amountPaidSQL = 'COALESCE(
          (SELECT SUM(jobs_payments_advance.amount) 
           FROM jobs_payments_advance 
           WHERE jobs_payments_advance.jobRef = jobs.id 
          ), 
          0 
         )' ; 

    $result = $dbh->prepare("SELECT SQL_CALC_FOUND_ROWS jobs.id, jobs_states.state, jobs.creationDate, users.username, 
          entity_details.name, enquiries.id as enquiryId, pendingCancelation, 
          IF(entity_details.paymentTermsRef = 1, # Outer IF condition 
           IF($amountDueSQL-$amountPaidSQL = 0.00, # Inner IF condition 
            CONCAT('Paid in full (', $currency, $amountDueSQL, ')') # Inner IF TRUE 
           , # End of inner IF TRUE 
            IF($amountPaidSQL > 0, 
            CONCAT('Part paid (', $currency, $amountPaidSQL, ')'), 
            'Unpaid' 
           ) 
           ) # End of inner IF 

          , # End of TRUE for outer IF 
           (SELECT entity_payment_terms.term 
            FROM entity_details, entity_payment_terms 
            WHERE entity_details.paymentTermsRef 
              = 
              entity_payment_terms.id 
            AND entity_details.id = enquiries.entityRef 
           ) # End of FALSE for outer IF 
          ) AS payState, enquiries.orderNumber, 

          IF((SELECT COUNT(*) 
            FROM invoices_out, (SELECT * FROM invoices_out_reference GROUP BY jobRef) AS tb1 
          WHERE invoices_out.id = tb1.invoiceRef 
          AND tb1.jobRef = jobs.id) > 1, 
           'Part-invoiced', 
           (SELECT invoices_out.date 
            FROM invoices_out, (SELECT * FROM invoices_out_reference GROUP BY jobRef) AS tb1 
          WHERE invoices_out.id = tb1.invoiceRef 
          AND tb1.jobRef = jobs.id) 
          ) AS invoicedDate, 

          enquiries.id AS enquiryId, 

          IF((SELECT COUNT(*) 
            FROM invoices_out, (SELECT * FROM invoices_out_reference GROUP BY jobRef) AS tb1 
          WHERE invoices_out.id = tb1.invoiceRef 
          AND tb1.jobRef = jobs.id) > 1, 
           'Multiple invoices', 
           (SELECT invoices_out.id 
            FROM invoices_out, (SELECT * FROM invoices_out_reference GROUP BY jobRef) AS tb1 
          WHERE invoices_out.id = tb1.invoiceRef 
          AND tb1.jobRef = jobs.id) 
          ) AS invoiceNumber, 

          # If the state is 0 (i.e. they have an account, if true find out their payment terms, if false, instead reference the payment state directly. 
          (SELECT MAX(etaDate) FROM parts_trading WHERE parts_trading.enquiryRef = enquiries.id) AS maxEtaDate, 
          (SELECT COUNT(DISTINCT DATE(etaDate)) FROM parts_trading WHERE parts_trading.enquiryRef = enquiries.id) AS etaCounts, entity_credit_limits.creditLimit AS cLimit, 
          COALESCE((SELECT 
            SUM(qty*parts_trading_buying.buyingNet 
            /
            (SELECT rateVsPound FROM currencies WHERE currencies.id = parts_trading_buying.buyingCurrency)) 
            FROM parts_trading_buying 
            WHERE parts_trading_buying.enquiryRef = enquiries.id 
            ), 0 
            ) AS nonInvoicedBuyingCosts, 
          COALESCE((SELECT 
            SUM(feeAmountNet/(SELECT rateVsPound FROM currencies WHERE currencies.id = parts_trading_buying.buyingCurrency)) 
            FROM parts_trading_buying_charges, parts_trading_buying 
            WHERE parts_trading_buying_charges.partRef = parts_trading_buying.id 
            AND parts_trading_buying.enquiryRef = enquiries.id 
            ), 0 
           ) AS nonInvoicedBuyingFeeCosts, 
          (SELECT 
           SUM(quantity*parts_trading.sellingNet) 
            /
            COALESCE(
             (SELECT invoices_out.rate 
             FROM invoices_out, invoices_out_reference 
             WHERE invoices_out.id = invoices_out_reference.invoiceRef 
             AND invoices_out_reference.jobRef = jobs.id 
             LIMIT 1), 
             (SELECT rateVsPound 
             FROM currencies 
             WHERE currencies.id = parts_trading.sellingCurrency) 
            ) 
          FROM parts_trading 
          WHERE parts_trading.enquiryRef = enquiries.id 
          ) AS sellingParts, 
          COALESCE((SELECT 
            SUM(enquiries_custom_fees.feeAmountNet) 
            /
            COALESCE(
             (SELECT rate 
             FROM invoices_out, invoices_out_reference 
             WHERE invoices_out.id = invoices_out_reference.invoiceRef 
             AND invoices_out_reference.jobRef = jobs.id LIMIT 1), 
             (SELECT rateVsPound 
             FROM currencies 
             WHERE currencies.id = parts_trading.sellingCurrency 
             ) 
            ) 
            FROM enquiries_custom_fees, parts_trading 
            WHERE enquiries_custom_fees.enquiryRef = enquiries.id 
            AND parts_trading.enquiryRef = enquiries.id), 0) AS sellingFees, 
          COALESCE((SELECT 
            SUM(parts_shipping_out.shippingOutCost) 
            FROM parts_shipping_out, parts_shipping_arrival_dates, parts_shipping_v2 
            WHERE parts_shipping_out.arrivalsRef = parts_shipping_arrival_dates.id 
            AND parts_shipping_arrival_dates.shippingRef = parts_shipping_v2.id 
            AND parts_shipping_v2.jobRef = jobs.id 
            ), 0 
           ) AS actualShippingOutFromEua, 
          (SELECT 

           SUM(quantity*parts_trading.sellingNet) 
            /
            COALESCE(
             (SELECT invoices_out.rate 
             FROM invoices_out, invoices_out_reference 
             WHERE invoices_out.id = invoices_out_reference.invoiceRef 
             AND invoices_out_reference.jobRef = jobs.id 
             LIMIT 1), 
             (SELECT rateVsPound 
             FROM currencies 
             WHERE currencies.id = parts_trading.sellingCurrency) 
            ) 
           + 
           COALESCE((SELECT 
            SUM(enquiries_custom_fees.feeAmountNet) 
            /
            COALESCE(
             (SELECT rate 
             FROM invoices_out, invoices_out_reference 
             WHERE invoices_out.id = invoices_out_reference.invoiceRef 
             AND invoices_out_reference.jobRef = jobs.id LIMIT 1), 
             (SELECT rateVsPound 
             FROM currencies 
             WHERE currencies.id = parts_trading.sellingCurrency 
             ) 
            ) 
            FROM enquiries_custom_fees 
            WHERE enquiries_custom_fees.enquiryRef = enquiries.id), 0) 
           - 
           COALESCE((SELECT 
            SUM(qty*parts_trading_buying.buyingNet 
            /
            (SELECT rateVsPound FROM currencies WHERE currencies.id = parts_trading_buying.buyingCurrency)) 
            FROM parts_trading_buying 
            WHERE parts_trading_buying.enquiryRef = enquiries.id 
            ), 0 
            ) 
           - 
           COALESCE((SELECT 
            SUM(feeAmountNet/(SELECT rateVsPound FROM currencies WHERE currencies.id = parts_trading_buying.buyingCurrency)) 
            FROM parts_trading_buying_charges, parts_trading_buying 
            WHERE parts_trading_buying_charges.partRef = parts_trading_buying.id 
            AND parts_trading_buying.enquiryRef = enquiries.id 
            ), 0 
           ) 
           - 
           COALESCE((SELECT 
            SUM(parts_shipping_out.shippingOutCost) 
            FROM parts_shipping_out, parts_shipping_arrival_dates, parts_shipping_v2 
            WHERE parts_shipping_out.arrivalsRef = parts_shipping_arrival_dates.id 
            AND parts_shipping_arrival_dates.shippingRef = parts_shipping_v2.id 
            AND parts_shipping_v2.jobRef = jobs.id 
            ), 0 
           ) 
           FROM parts_trading, parts_trading_buying 
           WHERE parts_trading.enquiryRef = enquiries.id 
           AND parts_trading_buying.counterpartRef = parts_trading.id 
          ) AS margin 
          FROM jobs, 
          jobs_states, enquiries, users, jobs_payment_status, entity_details 
          LEFT JOIN entity_credit_limits ON entity_details.id = entity_credit_limits.entityRef 
          WHERE jobs.stateRef = jobs_states.id 
          AND IF(paymentStateRef = 0, 1, (jobs_payment_status.id = jobs.paymentStateRef)) 
          #^If true it causes a result for each payment state (i.e. 3), so we group on state below, shouldn't cause probs. 
          AND jobs.enquiryRef = enquiries.id 
          AND enquiries.entityRef = entity_details.id 
          AND users.id = enquiries.traderRef 
          AND enquiries.traderRef = ? 
           LIMIT ?, ?") ; 

如果我嘗試設置上面3.5GB的Apache PHP執行內存無法啓動(我使用的XAMPP)。我必須使用32位版本的PHP?這對於INNODB_BUFFER_POOL_SIZE來說是相同的,我希望它是14GB,但是如果我這樣做的話mysql將不會啓動。

+0

什麼是查詢?你還可以提供相關的表格+索引... – BugFinder

+0

索引佔用大量空間,如果你在很多列上定義了索引,可能會導致問題 –

回答

1

我不認爲這是一個數據庫相關的問題,因爲這種錯誤(內存不足(需要268435427字節))大部分時間由PHP(無限循環或類似的東西可能是問題)拋出。

+0

即使我在PHPMyAdmin中單獨運行查詢?我仍然得到錯誤。 – imperium2335

+0

試着用mysql直接運行它。也許PHP的執行內存限制很低。 –

0

現在(兩分鐘的時間),您可以使用MySQLCalculator.com查看基本的RAM佔用空間。 如果配置中的每個連接RAM條目都有一個前導#,那麼您將運行良好,實際上要好得多。使用read_rnd_buffer_size = 24M的行而不是默認的256K,您正在讀取96倍以上的索引信息。