1. 程式人生 > >關於更新表結構時碰到的DDL鎖導致資料庫無法連線

關於更新表結構時碰到的DDL鎖導致資料庫無法連線

記一次更新表結構時語句一直處於等待無法執行的解決辦法

我們在更新資料庫表結構的時候,當資料庫有連線正在進行中的事務時,那麼你的更新請求會處於一個等待的狀態,一直等待到當前未提交的事務完成之後才會進行更新操作,但是這個未提交的事務會需要多久時間完成對我們來講是一個未知數,(自己第一次碰到這個情況的時候,竟然以為是資料記錄太多需要等待更新,等了半個小時... 愚蠢)在這個等待期間,所有的後續連線請求都會被掛起,等待事務提交完成後更新操作完成才會執行,邏輯是這樣的:有個事務1在查詢表a,一直佔著不釋放,那麼這個時候執行ddl操作,就會被事務1阻塞,直到事務1被提交或者被kill。如果當你在更新表結構時碰到了這種情況,不要等,等的越久你會發現自己越蠢。

首先說一下我們在執行ddl操作前需要注意的幾點:

第一點:

  不要使用navicat進行該操作,在你使用sql語句時,卡死掉我們ctrl+c結束正在執行的語句就好了,但是當我們利用navicat這種第三方工具連線時,一旦語句卡死,navicat這個程式也會無響應,並且!你將程式程序結束掉仍然無法停止正在執行的語句!(大坑!)

第二點:

  在更新前要挑選一個業務的低峰期進行更新,這個是在詢問阿里怎樣避免因為更新時出現此機制影響線上環境時阿里告訴我的辦法,emmm...

接下來說一下碰到這種問題時我們應該怎麼去解決:

第一點:

  我們在執行ddl操作前可以執行一下 select * from information_schema.innodb_trx 來看一下我們當前有沒有未提交的事務,可根據結果中的trx_state來看當前執行緒的狀態

第二點:

  在上條語句的查詢結果中我們可以找到有一個trx_mysql_thread_id列,這個列名對應的值我們可以在show processlist中找到對應的記錄,找到後可以檢視對應記錄的host列以及對應的使用者和庫,說明該主機還有連線沒有斷開

第三點:

  在找到這些資訊之後我們判斷該條連線是否可以kill,如果可以,我們可以 kill id(替換為對應連線的trx_mysql_thread_id) 之後再進行ddl操作

  這時沒有了未提交需要等待的事務,我們的表結構更新語句便會順利執行成功。