程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MYSQL入門知識 >> play a prank on DBA

play a prank on DBA

編輯:MYSQL入門知識
 

各位與公司的mysql DBA有仇嗎? 如果有仇的話,今天就告訴你們一個報仇的方法吧~

必需條件:
1) 能夠連接到mysql 並執行查詢,只讀權限就足夠了。
2) 數據庫中有innodb表,且有權限start transaction.
3) 保持此連接不斷開。
4) 存在其它線程對數據庫的innodb表進行寫入, 有大型事務操作就更好了。

操作:
連接到mysql之後:


BEGIN; --開啟事務。
SELECT * FROM tbl LIMIT 1; -- 隨意找一張innodb表查詢一下。
 

然後保持連接不斷開,一直等待就行了。。

過了N久之後, DBA就會發現數據庫貌似出了點問題,哈哈哈。

即使DBA使用show processlist, 也只能看到你的連接處於SLEEP狀態,Time比較長而已。

原理:
為了支持回滾與MVCC,innodb使用了undo log,保存在global table space中(ibdata1)?,這部分空間稱為“rollback segment”。

比如此時存在二個事務A與B。
A 先在tbl表中進行了查詢,然後B試圖從 tbl中更新一條數據(不更新主鍵字段),從B的角度來看,必須是可以更新成功啦,那麼A如果再次在tbl表中查詢會怎樣? A必須要可以看到這條數據被更新之前的狀態,這樣才叫做ACID。

Innodb直接在clustered index中更新了這條數據,同時把原始數據寫入了undo log,並且新數據有一個指針DB_ROLL_PTR指向了undo log中原始數據的位置。

如此,A再次查詢tbl表的時候,發現此條數據的最後修改transaction為B, 那麼此條數據的當前狀態應該對A不可見(可以用show engine innodb status看一下A can see哪些transaction的改動),於是A使用DB_ROLL_PTR去undo log中查找原始記錄。

如果事務A與B都提交了,那麼也沒有回滾和MVCC的必要了,undo log中的原始記錄就可以被清除了。 事實上,mysql 有若干個獨立於innodb的purge線程,會按照從舊到新的順序讀取並刪除undo log,until遇到一個比事務A的transaction_id還要大的事務的undo log(until這句是我YY出來的,沒有實證)。 這其實就是一個垃圾回收的過程。

只要A不提交或者不回滾,隨著其它線程不斷地寫入undo log, undo log就會變得越來越龐大,purge線程無法進行垃圾回收。


------------
TRANSACTIONS
------------
Trx id counter 0 684279153
Purge done FOR trx's n:o < 0 684278300 undo n:o < 0 0
History list length 96
 

History list length 會越來越長~~ 而purge done會保持不變。

而且還有一種情況,DELETE語句並不是物理刪除,而是在clustered index中直接標記為刪除,然後由purge線程進行後續的物理刪除。 由於事務A阻止了purge線程,所以無法物理刪除這些記錄,表空間越來越大,最終會占用大量磁盤空間。

我們扮演的就是A的角色 。

羅索了這麼多,那就再多說幾句關於clustered index與secondary index與undo log,MVCC的關系:
1) INSERT 操作
INSERT為什麼需要寫undo log呢? 可是它確實是寫了…… 回滾時,直接從clustered index, secondary index與undo log中刪除即可。purge進程也可以從undo log中刪除它。

2) DELETE 操作
原記錄寫入undo log,在clustered index和secondary index中標記此記錄為刪除狀態。purge進程將其物理刪除。

3) UPDATE 操作
3.1) UPDATE 非索引字段
原記錄寫入undo log,新記錄在clustered index中更新。
3.2) UPDATE secondary index字段
原記錄寫入undo log, 新記錄在clustered index中更新,secondary index中原記錄標記為刪除,創建新記錄並寫入secondary index。

3.3) UPDATE clustered index字段
原記錄寫入undo log,在clustered index中把原記錄標記為刪除,在secondary index 中把原記錄標記為刪除,創建新記錄並寫入clustered index和secondary index。
 

 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved