2011-05-31 115 views
10

我有一個大的生產Web應用程序(Glassfish 3.1 + MySQL 5.5)。所有的表都是InnoDB。每幾天一次應用程序完全掛起。 SHOW FULL PROCESSLIST顯示許多簡單的插入或更新查詢在不同的表,但所有有狀態MySQL InnoDB掛在等待表級鎖

等待表級鎖

例子:

update user<br> 
set user.hasnewmessages = NAME_CONST('in_flag',_binary'\0' COLLATE 'binary') 
where user.id = NAME_CONST('in_uid',66381) 

insert into exchanges_itempacks 
set packid = NAME_CONST('in_packId',332149), type = NAME_CONST('in_type',1), itemid = NAME_CONST('in_itemId',23710872) 

查詢最長的「時間」是也在等待表級鎖。 請幫忙弄清楚爲什麼MySQL試圖獲得級別鎖定以及可以鎖定所有這些表的內容。所有關於InnoDB鎖定的文章都說如果你不強迫它這樣做,這個引擎就不使用表鎖。

my.cnf有這樣的:

innodb_flush_log_at_trx_commit = 0 
innodb_support_xa = 0 
innodb_locks_unsafe_for_binlog = 1 
innodb_autoinc_lock_mode=2 

二進制日誌是關閉的。我根本沒有「LOCK TABLES」或其他明確的鎖定命令。交易記錄爲READ_UNCOMMITED

SHOW ENGINE INNODB STATUS輸出: http://avatar-studio.ru:8080/ph/imonout.txt

+0

爲什麼你的隔離級別設置爲「READ_UNCOMMITED」,它是一個髒模式,我絕不會建議將它設置在生產服務器上, – 2011-06-03 13:21:16

+0

這裏可能有一些有用的信息:[InnoDB Lock Modes](http:///dev.mysql.com/doc/refman/5.0/en/innodb-lock-modes.html),特別是文檔後面描述的意圖鎖定和死鎖的可能原因。最後還要注意用戶的評論。 – Mike 2011-07-12 06:58:05

回答

1

我覺得有一些當MySQL執行全表鎖(即使用自動增量)的情況。 我找到了一個可能會對您有幫助的鏈接:http://mysqldatabaseadministration.blogspot.com/2007/06/innodb-table-locks.html

此外,還審查java持久性代碼具有所有con的提交/回滾和關閉。 (總是在finally塊中關閉。)

嘗試在MySQL配置中設置innodb_table_locks=0http://dev.mysql.com/doc/refman/5.0/en/innodb-parameters.html#sysvar_innodb_table_locks

只是一些想法...

+1

Andrey已經有了innodb_autoinc_lock_mode = 2,它可以確保沒有插入式語句帶有任何自動鎖定。 – 2011-06-03 13:20:38

0

這看似簡單,但你沒有一個長期運行的SELECT語句可能是鎖定了更新和插入?有沒有查詢實際上運行,並沒有鎖定?

0

您是否考慮過使用MyISAM而不是InnoDB?

如果您沒有使用任何事務功能,MyISAM可能會更有意義。 它更簡單,更易於優化,並且由於它沒有複雜的事務功能,所以更容易在my.cnf中進行配置。

另外,根據您的應用創建的數據庫類型,MyISAM可能更合適。我更喜歡MyISAM來讀取大量的應用程序,同樣,配置和理解起來也更容易。

其他建議:

  • 這可能是一個好主意,找到一種方法,在你的SQL沒有使用NAME_CONST。 "This function was added in MySQL 5.0.12. It is for internal use only." 當一個開源產品的文檔說明了這一點時,它可能是個好主意,值得注意。

  • 默認情況下,MySQL的存儲所有InnoDB表1箇中的巨大文件&模式數據,有可能是某種操作系統級別上propogates到MySQL,防止所有表訪問特定文件鎖定的。通過使用innodb_file_per_table選項,您可以消除該潛在問題。這也使得MySQL更加節省空間。

0
在這種情況下

,你必須創建具有相同的列彼此幾種不同的數據庫表,並沒有嵌入更多的則3000行的每個表,在這種情況下,如果要輸入更多的數據到表,你必須創建另一個動態表(使用代碼生成表)並向該表中插入新數據並訪問該表中的數據。在你的情況下,如果越來越多的表必須生成,那麼你必須創建新的數據庫。

我認爲這個技巧會幫助你更仔細地設計你的數據庫並解決錯誤。

4

您是否正在使用MSQLDump備份您的數據庫,但它仍在被您的應用程序訪問?這可能會導致這種行爲。

+0

這是我的生產基地的問題。我剛剛讀到,可以通過使用innodb-databases的選項-single-transaction --quick來解決這個問題,所以我會嘗試。 – runholen 2014-08-15 06:48:27

1

我看到你在你的代碼中使用NAME_CONST。只是儘量不要使用它。你知道,mysql有時可能會出問題(我也發現了一些bug),所以我建議不要依賴那些不常見/經過很好測試的功能。它與列名有關,所以它可能會鎖定某些東西?那麼它不應該隻影響結果,但是誰知道呢?這是可疑的。此外,這被標記爲僅供內部使用的功能。