## 背景
我們知道MySQL的主備同步是通過binlog在備庫重放進行的,IO線程把主庫binlog拉過去存入relaylog,然后SQL線程重放 relaylog 中的event,然而這種模式有一個問題就是SQL線程只有一個,在主庫壓力大的時候,備庫單個SQL線程是跑不過主庫的多個用戶線程的,這樣備庫延遲是不可避免的。為了解決這種n對1造成的備庫延遲問題,5.6 引入了并行復制機制,即SQL線程在執行的時候可以并發跑。
關于其背后的設計思想,可以參考這幾個worklog?[WL#4648](http://dev.mysql.com/worklog/task/?id=4648),[WL#5563](http://dev.mysql.com/worklog/task/?id=5563),[WL#5569](http://dev.mysql.com/worklog/task/?id=5569),[WL#5754](http://dev.mysql.com/worklog/task/?id=5754),[WL#5599](http://dev.mysql.com/worklog/task/?id=5599),之前的月報也對并行復制原理進程了闡述,讀者朋友可以[回顧下](http://mysql.taobao.org/index.php?title=MySQL%E5%86%85%E6%A0%B8%E6%9C%88%E6%8A%A5_2015.01#MySQL_.C2.B7_.E4.BC.98.E5.8C.96.E6.94.B9.E8.BF.9B.C2.B7_.E5.A4.8D.E5.88.B6.E6.80.A7.E8.83.BD.E6.94.B9.E8.BF.9B.E8.BF.87.E7.A8.8B)。
本篇將從代碼實現角度講述并行復制是如何做的,分析基于MySQL 5.6.26。
## 準備知識
### binlog
binlog 是對數據庫更改操作的記錄,里面是一個個的event,如類似下面的event序列:
~~~
Query_log
Table_map
Write/Delete/Update_row_event
Xid
~~~
關于每個event的含義可以參考[官方文檔](https://dev.mysql.com/doc/internals/en/binlog-event.html)。
### 配置
并行復制提供了幾個參數配置,可以通過修改參數值對其進行調節。
~~~
slave_parallel_workers // worker 線程個數
slave-checkpoint-group // 隔多少個事務做一次 checkpoint
slave-checkpoint-period // 隔多長時間做一次 checkpoint
slave-pending-jobs-size-max // 分發給worker的、處于等待狀態的event的大小上限
~~~
### 概念術語
下面是并行復制中用到幾個概念:
~~~
MTS // Multi-Threaded Slave,并行復制
group // 一個事務在binlog中對應的一組event序列
worker // 簡稱W,event 執行線程,MTS新引入的
Coordinator // 簡稱C,分發協作線程,就是之前的 SQL線程
checkpoint // 簡稱CP,檢查點,C線程在滿足一定條件下去做,目的是收集W線程執行完信息,向前推動執行位點
B-event // 標志事務開始的event,BEGIN 這種Query或者GTID
G-event // 包含分發信息的event,如Table_map、Query
T-event // 標志事務結束的event,COMMIT/ROLLBACK 這種Query 或者XID
~~~
### 相關代碼文件
sql/rpl_rli_pdb.h // pdb的是 parallelized by db name簡寫[WL#5563](http://dev.mysql.com/worklog/task/?id=5563)
sql/rpl_rli_pdb.cc
sql/rpl_slave.cc
sql/log_event.cc
sql/rpl_rli.h
### 并行執行原則
1. 并行執行的基本模型是生產者-消費者,C線程將event按db插入各W線程的任務隊列,W線程從隊列里取出event執行;

2. 同一個group(事務)內的event都發給同一個worker,保證事務的一致性;
3. 分發關系由包含db信息的event(G-evnet)決定,其它event按決定好的關系進行分發;
## 重要數據結構
1. `db_worker_hash_entry`,db->worker 映射關系,也即分發關系,所有的分發關系緩存在C的一個HASH表中(APH)
~~~
- db // db 名
- worker // 指向worker的指針,表示被分發到的W線程
- usage // 有多少正在分發的group用到這個關系
- temporary_tables // 用于在C和W之前傳遞臨時表
~~~
2. `slave_job_item`,worker的jobs隊列的成員
~~~
- data // 就是一個binlog event
~~~
3. `circular_buffer_queue`,用DYNAMIC_ARRAY arrary實現的一個首尾相連的環形隊列,是其他重要數據結構的基類
~~~
- Q // 底層用到的 DYNAMIC_ARRAY
- size // Queue 的容量
- avail // 隊列尾
- entry // 隊列頭
- len // 隊列實際大小
- de_queue() // 出隊操作
- de_tail() // 尾部出隊
- en_queue() // 入隊
- head_queue() // 取隊列頭,但是不出隊
~~~
4. `Slave_job_group`,維護一個正在執行的事務的信息,如對應的位點信息、事務分發到的worker、有沒有執行完等。
~~~
- group_master_log_name // 對應主庫的 binlog 文件名
- group_master_log_pos // 對應在主庫 binlog 中的位置
- group_relay_log_name // 對應備庫 relaylog 文件名
- group_relay_log_pos // 對應在備庫 relaylog 中的位置
- worker_id // 對應的worker的id
- worker // worker 指針
- total_seqno // 當前group是啟動以來執行的第幾個group
- master_log_pos // group中B-event的位置
- checkpoint_seqno // 當前group是從上次做完CP后的第幾個group
- checkpoint_log_pos // worker收到checkpoint信號后更新
- checkpoint_log_name // 同上
- checkpoint_relay_log_pos // 同上
- checkpoint_relay_log_name // 同上
- done // 這個group是否已經被worker commit掉
- shifted // checkpoint 的時候shift值
- ts // 時間,更新SBM
- reset() // 重置上面的成員變量
~~~
5. `Slave_committed_queue`,維護分發執行的group信息,是`circular_buffer_queue`的子類,隊列里存的時?`Slave_job_group`
~~~
- lwm // 類型是Slave_job_group,低水位(Low-Water-Mark),表示上次CP執行到的位置
- last_done // 類型是一個DYNAMIC_ARRAY,里面存的是Slave_job_group:total_seqno,表示每個worker執行到第幾個group
- assigned_group_index // 正在分發的group在GAQ中的位置
- move_queue_head() // 做checkpoint時,把已經commit的group移出隊列
- get_job_group() // 返回隊列指定位置的Slave_job_group
- en_queue() // 入隊一個 Slave_job_group
~~~
6. `Slave_jobs_queue`,任務隊列,也是`circular_buffer_queue`的子類,隊列里存的是`slave_job_item`,每個worker有一個這樣的任務隊列
~~~
- overfill // 隊列滿標志
- waited_overfill // 隊列滿的次數
~~~
7. `Slave_worker`,對應一個worker,`Relay_log_info`?的子類
~~~
- jobs // 類型是 Slave_jobs_queue,C分發過來的event都放在這里面
- c_rli // 指向C的指針
- curr_group_exec_parts // 類型是 DYNAMIC_ARRAY,里面存的是當前group用到的分發關系,是指向APH成員的指針,簡寫CGEP
- curr_group_seen_begin // 當前所在 group 有沒有解析到 B-event
- id // worker 的id標識
- last_group_done_index // worker上一次執行的group在GAQ中的位置
- gaq_index // worker 當前執行的的事務在GAQ中的位置
- usage_partition // worker用到的分發關系個數
- end_group_sets_max_dbs // 和串行執行相關的
- bitmap_shifted // CP后bitmap需要偏移的距離,用于調整 group_executed
- wq_overrun_cnt // 超載多少
- overrun_level // 超載指標
- underrun_level // 饑餓指標
- excess_cnt // 用于往mts_wq_excess_cnt累計
- group_executed // 類型是 MY_BITMAP,標示CP后執行的group
- group_shifted // 類型是 MY_BITMAP,計算group_executed,臨時用作中間變量
- running_status // 標識 worker 線程的狀態,可以有 NOT_RUNNING、RUNNING、ERROR_LEAVING、KILLED
- slave_worker_ends_group () // 當一個group執行完或者異常終止時會調用
- commit_positions() // group執行完是調用,用于更新位點和bitmap
- rollback_positions() // 回滾bitmap
~~~
8. `Relay_log_info`,對應C線程,在MTS之前對應SQL線程,為了支持并行復制,在原來的基礎上又加了一些成員
~~~
- mapping_db_to_worker // 非常重要的成員,類型是HASH,用于緩存所有的分發關系,APH(Assigned Partition Hash),目的能通過db快速找到映射關系,但HASH長度大于mts_partition_hash_soft_max(固定16)時,會對沒有使用的映射關系進行回收。
- workers // 類型是 DYNAMIC_ARRAY,成員是一個個Slave_worker
- pending_jobs // 一個統計信息,表示待執行job個數
- mts_slave_worker_queue_len_max // 每個worker最多能容納jobs的個數,目前hard code是16384
- mts_pending_jobs_size // 所有worker的job占的內存
- mts_pending_jobs_size_max // 所有worker的job占的內存,對應配置 slave_pending_jobs_size_max
- mts_wq_oversize // 標示job占用內存已達上限
- gaq // 非常重要的成員,代碼注釋里經常提到的GAQ,類型是Slave_committed_queue,存的成員是Slave_job_group,大小對應配置 slave-checkpoint-group,用于W和C交互
- curr_group_assigned_parts // 類型是 DYNAMIC_ARRAY,當前group中已經分配的event的映射關系,可以和Slave_worker的curr_group_exec_parts對應,簡寫CGAP
- curr_group_da // 類型是DYNAMIC_ARRAY,對于還無法決定分發worker的event,先存在這里
- mts_wq_underrun_w_id // 標識比較空閑的worker的id
- mts_wq_excess_cnt // 標示worker的超載情況
- mts_worker_underrun_level // 當W的任務隊列大小低于這個值的認為處于饑餓狀態
- mts_coordinator_basic_nap // 當work負載較大時,C線程sleep,會用到這個值
- opt_slave_parallel_workers // 對應配置 slave_parallel_workers
- slave_parallel_workers // 當前實際的worker數
- exit_counter // 退出時用
- max_updated_index // 退出時用
- checkpoint_seqno // 上次CP后分發的group個數
- checkpoint_group // 對應配置 mts_checkpoint_group
- recovery_groups // 類型是 MY_BITMAP,恢復時用到
- mts_group_status // 分發線程所處的狀態,取值為 MTS_NOT_IN_GROUP、MTS_IN_GROUP、MTS_END_GROUP、MTS_KILLED_GROUP
- mts_events_assigned // 分發的event計數
- mts_groups_assigned // 分發的group計數
- least_occupied_workers // 類型是 DYNAMIC_ARRAY,從注釋將worker按從空閑到繁忙排序的一個數組,用于先worker用,但是實際并未用到。
- last_clock // 上次做checkpoint的時間
~~~
9. 其它方法
~~~
map_db_to_worker() // 把db映射給worker
get_least_occupied_worker() // 獲取負載最小的worker
wait_for_workers_to_finish() // 等待worker完成,并發臨時轉成串行是用到
append_item_to_jobs() // 把任務分發給 worker
mts_move_temp_table_to_entry() // 用于傳遞臨時表
mts_move_temp_tables_to_thd() // 同上
~~~
## 初始化
和單線程SQL相比,MTS需要初始化新加的MTS變量和啟動worker線程。
主要是`slave_start_workers()`這個函數。會初始化C線程的MTS變量,如workers、curr_group_assigned_parts、curr_group_da、gaq等,接著調用`init_hash_workers()`?初始化HASH表mapping_db_to_worker,在這些做完后依次調用?`slave_start_single_worker()`?初始化每個worker并啟動W線程。worker 的的初始化包括jobs任務隊列、curr_group_exec_parts 等相關變量,其中jobs長度目前是固定的16384,目前還不可配置;worker線程的主函數是`handle_slave_worker()`,不停的調用`slave_worker_exec_job()`來執行C分配的event。
## Coordinator 分發協作
分發線程主體和之前的SQL線程基本是一樣的,不停的調用?`exec_relay_log_event()`?函數。`exec_relay_log_event()`主要分2部分,一是調用`next_event()`讀取relay log,一是`apply_event_and_update_pos()`?做分發。
`next_event()`?比較簡單,就是不停的用?`Log_event::read_log_event()`?從relay log 讀取event,除此之外還會調用`mts_checkpoint_routine()`?做checkpoint,后面會詳細講checkpiont過程。
`apply_event_and_update_pos()`進行分發的入口是`Log_event::apply_event()`,如果沒有開MTS,就是原來的邏輯,SQL線程直接執行event,如果開了MTS的話,調用`get_slave_worker()`,這個是分發的主邏輯。
在介紹分發邏輯前,先將所有的binlog event 可以分下類(代碼里是這么分的):
~~~
B-event // BEGIN(Query) 或者 GTID
G-event // 包含db信息的event,Table_map 或者 Query
P-event // 一般放在G-event前的,如int_var、rand、user_var等
R-event // 一般放在G-event后的,如各種Rows event
T-event // COMMIT/ROLLBACK(Query) 或者XID
~~~
分發邏輯是這樣的:
1. 如果是B-event,表明是事務的開始,mts_groups_assigned 計數加1,同時GAQ中入隊一個新的group,表示一個新的事務開始,然后把event放入curr_group_da,因為B-event沒有db信息,還不知道分發給哪個worker;
2. 如果是G-event,event里包含db信息,就需要按這個db找到一個分發到的worker,worker選擇機制是`map_db_to_worker()`實現。調用`map_db_to_worker()`時,有2個參數比較重要,一個是dbname,這個就是分發關系的key,一個是last_worker,表示當前group中event上一次分發到的worker(last_assigned_worker);
* 在當前group已經用到的映射關系(curr_group_assigned_parts CGAP)中找,如果有同db的映射關系,就直接返回last_worker;如果找不到,就去APH中按db名搜索;
* 如果APH中搜到的話,分3種情況,a) 這個映射關系沒有group用到,就直接把db映射為last_worker,如果last_worker為空的主話,就找一個最空閑的worker,`get_least_occupied_worker()`?b) 這個映射關系有group用,并且對應的worker和last_worker一樣,就用last_worker,映射關系引用計數加1 c) 如果映射關系對應的worker和last_worker不一樣,這表示有沖突,就需要等到引用這個映射關系的group全部執行完,然后把db映射為last_worker;
* 如果沒搜到的話,就新生成一個映射關系,key用db,value用last_worker,如果last_worker為空的話,選最空閑的worker,`get_least_occupied_worker()`,并把新生成的映射插入到APH中,如果HASP表長度大于 mts_partition_hash_soft_max 的話,在插入前會對APH做一次收縮,從中去除掉沒有被group引用的映射關系;
* 把選擇的映射關系插入到 curr_group_assigned_parts 中。
3. 如果是其它event,worker直接用last_assigned_worker。
什么時候切換為串行?
如果G-event包含的db個數大于MAX_DBS_IN_EVENT_MTS(16個),或者更新的表被外鍵依賴,那么就需要串行執行當前group。串行固定選用第0個worker來執行,在分發前會等待其它worker全部執行完,在分發后會等待所有worker執行完。gropu執行完后自動切換為并行執行。
worker 確定好了,下一步就是分發event了,入口函數?`append_item_to_jobs()`。這個函數的作用非常明確,就是把event插入到worker的jobs隊列中,在插入前會有對event大小有檢查:
1. 如果event大小已經超過了等待任務大小的上限(配置slave-pending-jobs-size-max ),就報event太大的錯,然后返回;
2. 如果event大小+已經在等待的任務大小超過了slave-pending-jobs-size-max,就等待,至到等待隊列變小;
3. 如果當前的worker的隊列滿的話,也等待。
## Worker 執行
W線程執行的主邏輯是?`slave_worker_exec_job()`:
1. 從自己的job隊列里取出event;
2. 根據event的信息,來更新worker中的變量,如curr_group_exec_parts(CGEP)、future_event_relay_log_pos、gaq_index等;
3. 執行event,`do_apply_event_worker()`,最終調用每個event的`do_apply_event()`方法,和單線程下一樣;
4. 如果是T event,調用?`slave_worker_ends_group()`,表示一個事務已經執行完了,a) 更新位點,通過`commit_positions()`,更新事務在GAQ中對應的`Slave_job_group`,這樣C就知道W執行到哪了,另外還會更新W的bitmap信息(如果是xid event,在apply_event中就會調用commit_positions) b) 清空 curr_group_exec_parts,將映射關系中的引用數減1;
5. 更新C的隊列統計信息,如等待執行任務數pending_jobs,等待執行任務大小mts_pending_jobs_size等;
6. 更新 overrun 和 underrun 狀態。
分發和執行邏輯可以用下圖簡單表示:

C線程在GAQ中插入group,標示一個要執行的事務,接著確定分發關系(從CGAP或者APH中,或者生成新的),然后按映射關系把event分發給對應worker的job隊列;worker在執行event過程中更新自己的CGEP,在執行完整個group后,根據CGEP中的記錄去更新APH中引用關系的計數,同時把GAQ中的對應group標示為done。
## checkpoint 過程
如前所述,C線程會在從relaylog讀取event后,會嘗試做checkpoint,入口函數是`mts_checkpoint_routine()`。checkpoint的作用是把worker執行完的事務從GAQ中去除,向前推進事務完成點。
有2個條件會觸發checkpoint:
1. 當前時間距上次checkpoint已經超過配置 mts-checkpoint-period,這時會嘗試做一次checkpoint,不管有沒有向前推進事務;
2. 上一次checkpoint后分發的事務數已經到達checkpoint設置上限(slave-checkpoint-group),這時會強制做checkpoint,如果一次checkpoint沒成功,會一直重試,直至成功。
GAQ中的事務推進通過?`Slave_committed_queue::move_queue_head()`?實現,從前向后掃描GAQ中的group:
1. 如果當前group已經完成(通過標志`Slave_job_group.done`標志確認),就把這個group出隊,同時把這個出隊的group信息賦給低水位lwm,向前推進;
2. 如果遇到沒有完成的group,就是遇到一個gap,表示對應worker還沒執行完當前group,checkpoint不能再向前推進了,到此結束,返回值就是退出前已經推進的group個數。

## slave 停止
類似單線程復制,stop slave 命令會終止C線程和W線程的運行。
C線程收到退出信號后,會先調用`slave_stop_workers()`終止W線程,過程如下:
1. 依次把每個運行中的 worker 的 runnig_status 設置`Slave_worker::STOP`,同時設置worker執行終止位置`rli->max_updated_index`;
2. C線程等待所有W線程終止(`w->running_status == Slave_worker::NOT_RUNNING`);
3. 調用`mts_checkpoint_routine()`,做一次checkpoint;
4. 釋放資源,如APH、GAQ、CGDA(curr_group_da)、CGAP(curr_group_assigned_parts)等。
W線程在`pop_jobs_item()`中會調用`set_max_updated_index_on_stop()`,會檢查2個條件 1) job隊列是空的,2) 當前worker執行的事務在GAQ中的位置,是否已經超過`rli->max_updated_index`;任一條件滿足就設置狀態 running_status 為?`Slave_worker::STOP_ACCEPTED`,表示開始退出。
從上面的邏輯可以看出,在收到stop信號后,worker線程會等正在執行的group完成后,才會退出。
## 異常退出
W被kill或者執行出錯
1. `slave_worker_exec_job()`?進入錯誤處理邏輯,調用`Slave_worker::slave_worker_ends_group()`,給C線程發KILL_QUERY信號,然后做相關變量的清理,把job隊列的任務全部清理掉,最終把running_status置為`Slave_worker::NOT_RUNNING`,表示結束;
2. C線程收到kill信號后,停止分發,然后進入`slave_stop_workers()`邏輯,給活躍的W線程發送STOP信號;
3. 其它W線程收到STOP信號后,會處理job隊列中所有的event;
4. 和stop slave不同的是,C線程最后不會做checkpoint。
C被kill
C被kill的處理邏輯和stop slave差不多,不同之處在于等worker全部終止后,不會做checkpoint。
## 恢復
Slave線程重啟(正常關閉或者異常kill)后,需要根據Coordinator和每個Worker的記錄信息來進行恢復,推進到一個一致狀態后再開始并行,詳細過程我們下期月報再分析。
## 存在的問題
5.6 的MTS是按db來進行分發的,分發粒度太大,如果只有一個db的時候,就沒有并發性了,所有group都分給一個worker,就變成單線程執行了。一個簡單的優化改進是改成按table來分發,只需要把分發的key從dbname改成dbname + tablename,整體分發邏輯不需要變動。再進一步,如果遇到熱點表更新呢,這時候binlog里記錄的event都是針對一個表的更新,又會變成串行執行。這個時候就需要變化一下分發測略嘍,如按事務維度進行分發,這個策略對源碼的改動就會比較大些,有需要的同學可以試試:-)
- 數據庫內核月報目錄
- 數據庫內核月報 - 2016/09
- MySQL · 社區貢獻 · AliSQL那些事兒
- PetaData · 架構體系 · PetaData第二代低成本存儲體系
- MySQL · 社區動態 · MariaDB 10.2 前瞻
- MySQL · 特性分析 · 執行計劃緩存設計與實現
- PgSQL · 最佳實踐 · pg_rman源碼淺析與使用
- MySQL · 捉蟲狀態 · bug分析兩例
- PgSQL · 源碼分析 · PG優化器淺析
- MongoDB · 特性分析· Sharding原理與應用
- PgSQL · 源碼分析 · PG中的無鎖算法和原子操作應用一則
- SQLServer · 最佳實踐 · TEMPDB的設計
- 數據庫內核月報 - 2016/08
- MySQL · 特性分析 ·MySQL 5.7新特性系列四
- PgSQL · PostgreSQL 邏輯流復制技術的秘密
- MySQL · 特性分析 · MyRocks簡介
- GPDB · 特性分析· Greenplum 備份架構
- SQLServer · 最佳實踐 · RDS for SQLServer 2012權限限制提升與改善
- TokuDB · 引擎特性 · REPLACE 語句優化
- MySQL · 專家投稿 · InnoDB物理行中null值的存儲的推斷與驗證
- PgSQL · 實戰經驗 · 旋轉門壓縮算法在PostgreSQL中的實現
- MySQL · 源碼分析 · Query Cache并發處理
- PgSQL · 源碼分析· pg_dump分析
- 數據庫內核月報 - 2016/07
- MySQL · 特性分析 ·MySQL 5.7新特性系列三
- MySQL · 特性分析 · 5.7 代價模型淺析
- PgSQL · 實戰經驗 · 分組TOP性能提升44倍
- MySQL · 源碼分析 · 網絡通信模塊淺析
- MongoDB · 特性分析 · 索引原理
- SQLServer · 特性分析 · XML與JSON應用比較
- MySQL · 最佳實戰 · 審計日志實用案例分析
- MySQL · 性能優化 · 條件下推到物化表
- MySQL · 源碼分析 · Query Cache內部剖析
- MySQL · 捉蟲動態 · 備庫1206錯誤問題說明
- 數據庫內核月報 - 2016/06
- MySQL · 特性分析 · innodb 鎖分裂繼承與遷移
- MySQL · 特性分析 ·MySQL 5.7新特性系列二
- PgSQL · 實戰經驗 · 如何預測Freeze IO風暴
- GPDB · 特性分析· Filespace和Tablespace
- MariaDB · 新特性 · 窗口函數
- MySQL · TokuDB · checkpoint過程
- MySQL · 特性分析 · 內部臨時表
- MySQL · 最佳實踐 · 空間優化
- SQLServer · 最佳實踐 · 數據庫實現大容量插入的幾種方式
- 數據庫內核月報 - 2016/05
- MySQL · 引擎特性 · 基于InnoDB的物理復制實現
- MySQL · 特性分析 · MySQL 5.7新特性系列一
- PostgreSQL · 特性分析 · 邏輯結構和權限體系
- MySQL · 特性分析 · innodb buffer pool相關特性
- PG&GP · 特性分析 · 外部數據導入接口實現分析
- SQLServer · 最佳實踐 · 透明數據加密在SQLServer的應用
- MySQL · TokuDB · 日志子系統和崩潰恢復過程
- MongoDB · 特性分析 · Sharded cluster架構原理
- PostgreSQL · 特性分析 · 統計信息計算方法
- MySQL · 捉蟲動態 · left-join多表導致crash
- 數據庫內核月報 - 2016/04
- MySQL · 參數故事 · innodb_additional_mem_pool_size
- GPDB · 特性分析 · Segment事務一致性與異常處理
- GPDB · 特性分析 · Segment 修復指南
- MySQL · 捉蟲動態 · 并行復制外鍵約束問題二
- PgSQL · 性能優化 · 如何瀟灑的處理每天上百TB的數據增量
- Memcached · 最佳實踐 · 熱點 Key 問題解決方案
- MongoDB · 最佳實踐 · 短連接Auth性能優化
- MySQL · 最佳實踐 · RDS 只讀實例延遲分析
- MySQL · TokuDB · TokuDB索引結構--Fractal Tree
- MySQL · TokuDB · Savepoint漫談
- 數據庫內核月報 - 2016/03
- MySQL · TokuDB · 事務子系統和 MVCC 實現
- MongoDB · 特性分析 · MMAPv1 存儲引擎原理
- PgSQL · 源碼分析 · 優化器邏輯推理
- SQLServer · BUG分析 · Agent 鏈接泄露分析
- Redis · 特性分析 · AOF Rewrite 分析
- MySQL · BUG分析 · Rename table 死鎖分析
- MySQL · 物理備份 · Percona XtraBackup 備份原理
- GPDB · 特性分析· GreenPlum FTS 機制
- MySQL · 答疑解惑 · 備庫Seconds_Behind_Master計算
- MySQL · 答疑解惑 · MySQL 鎖問題最佳實踐
- 數據庫內核月報 - 2016/02
- MySQL · 引擎特性 · InnoDB 文件系統之文件物理結構
- MySQL · 引擎特性 · InnoDB 文件系統之IO系統和內存管理
- MySQL · 特性分析 · InnoDB transaction history
- PgSQL · 會議見聞 · PgConf.Russia 2016 大會總結
- PgSQL · 答疑解惑 · PostgreSQL 9.6 并行查詢實現分析
- MySQL · TokuDB · TokuDB之黑科技工具
- PgSQL · 性能優化 · PostgreSQL TPC-C極限優化玩法
- MariaDB · 版本特性 · MariaDB 的 GTID 介紹
- MySQL · 特性分析 · 線程池
- MySQL · 答疑解惑 · mysqldump tips 兩則
- 數據庫內核月報 - 2016/01
- MySQL · 引擎特性 · InnoDB 事務鎖系統簡介
- GPDB · 特性分析· GreenPlum Primary/Mirror 同步機制
- MySQL · 專家投稿 · MySQL5.7 的 JSON 實現
- MySQL · 特性分析 · 優化器 MRR & BKA
- MySQL · 答疑解惑 · 物理備份死鎖分析
- MySQL · TokuDB · Cachetable 的工作線程和線程池
- MySQL · 特性分析 · drop table的優化
- MySQL · 答疑解惑 · GTID不一致分析
- PgSQL · 特性分析 · Plan Hint
- MariaDB · 社區動態 · MariaDB on Power8 (下)
- 數據庫內核月報 - 2015/12
- MySQL · 引擎特性 · InnoDB 事務子系統介紹
- PgSQL · 特性介紹 · 全文搜索介紹
- MongoDB · 捉蟲動態 · Kill Hang問題排查記錄
- MySQL · 參數優化 ·RDS MySQL參數調優最佳實踐
- PgSQL · 特性分析 · 備庫激活過程分析
- MySQL · TokuDB · 讓Hot Backup更完美
- PgSQL · 答疑解惑 · 表膨脹
- MySQL · 特性分析 · Index Condition Pushdown (ICP)
- MariaDB · 社區動態 · MariaDB on Power8
- MySQL · 特性分析 · 企業版特性一覽
- 數據庫內核月報 - 2015/11
- MySQL · 社區見聞 · OOW 2015 總結 MySQL 篇
- MySQL · 特性分析 · Statement Digest
- PgSQL · 答疑解惑 · PostgreSQL 用戶組權限管理
- MySQL · 特性分析 · MDL 實現分析
- PgSQL · 特性分析 · full page write 機制
- MySQL · 捉蟲動態 · MySQL 外鍵異常分析
- MySQL · 答疑解惑 · MySQL 優化器 range 的代價計算
- MySQL · 捉蟲動態 · ORDER/GROUP BY 導致 mysqld crash
- MySQL · TokuDB · TokuDB 中的行鎖
- MySQL · 捉蟲動態 · order by limit 造成優化器選擇索引錯誤
- 數據庫內核月報 - 2015/10
- MySQL · 引擎特性 · InnoDB 全文索引簡介
- MySQL · 特性分析 · 跟蹤Metadata lock
- MySQL · 答疑解惑 · 索引過濾性太差引起CPU飆高分析
- PgSQL · 特性分析 · PG主備流復制機制
- MySQL · 捉蟲動態 · start slave crash 診斷分析
- MySQL · 捉蟲動態 · 刪除索引導致表無法打開
- PgSQL · 特性分析 · PostgreSQL Aurora方案與DEMO
- TokuDB · 捉蟲動態 · CREATE DATABASE 導致crash問題
- PgSQL · 特性分析 · pg_receivexlog工具解析
- MySQL · 特性分析 · MySQL權限存儲與管理
- 數據庫內核月報 - 2015/09
- MySQL · 引擎特性 · InnoDB Adaptive hash index介紹
- PgSQL · 特性分析 · clog異步提交一致性、原子操作與fsync
- MySQL · 捉蟲動態 · BUG 幾例
- PgSQL · 答疑解惑 · 詭異的函數返回值
- MySQL · 捉蟲動態 · 建表過程中crash造成重建表失敗
- PgSQL · 特性分析 · 談談checkpoint的調度
- MySQL · 特性分析 · 5.6 并行復制恢復實現
- MySQL · 備庫優化 · relay fetch 備庫優化
- MySQL · 特性分析 · 5.6并行復制事件分發機制
- MySQL · TokuDB · 文件目錄談
- 數據庫內核月報 - 2015/08
- MySQL · 社區動態 · InnoDB Page Compression
- PgSQL · 答疑解惑 · RDS中的PostgreSQL備庫延遲原因分析
- MySQL · 社區動態 · MySQL5.6.26 Release Note解讀
- PgSQL · 捉蟲動態 · 執行大SQL語句提示無效的內存申請大小
- MySQL · 社區動態 · MariaDB InnoDB表空間碎片整理
- PgSQL · 答疑解惑 · 歸檔進程cp命令的core文件追查
- MySQL · 答疑解惑 · open file limits
- MySQL · TokuDB · 瘋狂的 filenum++
- MySQL · 功能分析 · 5.6 并行復制實現分析
- MySQL · 功能分析 · MySQL表定義緩存
- 數據庫內核月報 - 2015/07
- MySQL · 引擎特性 · Innodb change buffer介紹
- MySQL · TokuDB · TokuDB Checkpoint機制
- PgSQL · 特性分析 · 時間線解析
- PgSQL · 功能分析 · PostGIS 在 O2O應用中的優勢
- MySQL · 引擎特性 · InnoDB index lock前世今生
- MySQL · 社區動態 · MySQL內存分配支持NUMA
- MySQL · 答疑解惑 · 外鍵刪除bug分析
- MySQL · 引擎特性 · MySQL logical read-ahead
- MySQL · 功能介紹 · binlog拉取速度的控制
- MySQL · 答疑解惑 · 浮點型的顯示問題
- 數據庫內核月報 - 2015/06
- MySQL · 引擎特性 · InnoDB 崩潰恢復過程
- MySQL · 捉蟲動態 · 唯一鍵約束失效
- MySQL · 捉蟲動態 · ALTER IGNORE TABLE導致主備不一致
- MySQL · 答疑解惑 · MySQL Sort 分頁
- MySQL · 答疑解惑 · binlog event 中的 error code
- PgSQL · 功能分析 · Listen/Notify 功能
- MySQL · 捉蟲動態 · 任性的 normal shutdown
- PgSQL · 追根究底 · WAL日志空間的意外增長
- MySQL · 社區動態 · MariaDB Role 體系
- MySQL · TokuDB · TokuDB數據文件大小計算
- 數據庫內核月報 - 2015/05
- MySQL · 引擎特性 · InnoDB redo log漫游
- MySQL · 專家投稿 · MySQL數據庫SYS CPU高的可能性分析
- MySQL · 捉蟲動態 · 5.6 與 5.5 InnoDB 不兼容導致 crash
- MySQL · 答疑解惑 · InnoDB 預讀 VS Oracle 多塊讀
- PgSQL · 社區動態 · 9.5 新功能BRIN索引
- MySQL · 捉蟲動態 · MySQL DDL BUG
- MySQL · 答疑解惑 · set names 都做了什么
- MySQL · 捉蟲動態 · 臨時表操作導致主備不一致
- TokuDB · 引擎特性 · zstd壓縮算法
- MySQL · 答疑解惑 · binlog 位點刷新策略
- 數據庫內核月報 - 2015/04
- MySQL · 引擎特性 · InnoDB undo log 漫游
- TokuDB · 產品新聞 · RDS TokuDB小手冊
- PgSQL · 社區動態 · 說一說PgSQL 9.4.1中的那些安全補丁
- MySQL · 捉蟲動態 · 連接斷開導致XA事務丟失
- MySQL · 捉蟲動態 · GTID下slave_net_timeout值太小問題
- MySQL · 捉蟲動態 · Relay log 中 GTID group 完整性檢測
- MySQL · 答疑釋惑 · UPDATE交換列單表和多表的區別
- MySQL · 捉蟲動態 · 刪被引用索引導致crash
- MySQL · 答疑釋惑 · GTID下auto_position=0時數據不一致
- 數據庫內核月報 - 2015/03
- MySQL · 答疑釋惑· 并發Replace into導致的死鎖分析
- MySQL · 性能優化· 5.7.6 InnoDB page flush 優化
- MySQL · 捉蟲動態· pid file丟失問題分析
- MySQL · 答疑釋惑· using filesort VS using temporary
- MySQL · 優化限制· MySQL index_condition_pushdown
- MySQL · 捉蟲動態·DROP DATABASE外鍵約束的GTID BUG
- MySQL · 答疑釋惑· lower_case_table_names 使用問題
- PgSQL · 特性分析· Logical Decoding探索
- PgSQL · 特性分析· jsonb類型解析
- TokuDB ·引擎機制· TokuDB線程池
- 數據庫內核月報 - 2015/02
- MySQL · 性能優化· InnoDB buffer pool flush策略漫談
- MySQL · 社區動態· 5.6.23 InnoDB相關Bugfix
- PgSQL · 特性分析· Replication Slot
- PgSQL · 特性分析· pg_prewarm
- MySQL · 答疑釋惑· InnoDB丟失自增值
- MySQL · 答疑釋惑· 5.5 和 5.6 時間類型兼容問題
- MySQL · 捉蟲動態· 變量修改導致binlog錯誤
- MariaDB · 特性分析· 表/表空間加密
- MariaDB · 特性分析· Per-query variables
- TokuDB · 特性分析· 日志詳解
- 數據庫內核月報 - 2015/01
- MySQL · 性能優化· Group Commit優化
- MySQL · 新增特性· DDL fast fail
- MySQL · 性能優化· 啟用GTID場景的性能問題及優化
- MySQL · 捉蟲動態· InnoDB自增列重復值問題
- MySQL · 優化改進· 復制性能改進過程
- MySQL · 談古論今· key分區算法演變分析
- MySQL · 捉蟲動態· mysql client crash一例
- MySQL · 捉蟲動態· 設置 gtid_purged 破壞AUTO_POSITION復制協議
- MySQL · 捉蟲動態· replicate filter 和 GTID 一起使用的問題
- TokuDB·特性分析· Optimize Table
- 數據庫內核月報 - 2014/12
- MySQL· 性能優化·5.7 Innodb事務系統
- MySQL· 踩過的坑·5.6 GTID 和存儲引擎那會事
- MySQL· 性能優化·thread pool 原理分析
- MySQL· 性能優化·并行復制外建約束問題
- MySQL· 答疑釋惑·binlog event有序性
- MySQL· 答疑釋惑·server_id為0的Rotate
- MySQL· 性能優化·Bulk Load for CREATE INDEX
- MySQL· 捉蟲動態·Opened tables block read only
- MySQL· 優化改進· GTID啟動優化
- TokuDB· Binary Log Group Commit with TokuDB
- 數據庫內核月報 - 2014/11
- MySQL· 捉蟲動態·OPTIMIZE 不存在的表
- MySQL· 捉蟲動態·SIGHUP 導致 binlog 寫錯
- MySQL· 5.7改進·Recovery改進
- MySQL· 5.7特性·高可用支持
- MySQL· 5.7優化·Metadata Lock子系統的優化
- MySQL· 5.7特性·在線Truncate undo log 表空間
- MySQL· 性能優化·hash_scan 算法的實現解析
- TokuDB· 版本優化· 7.5.0
- TokuDB· 引擎特性· FAST UPDATES
- MariaDB· 性能優化·filesort with small LIMIT optimization
- 數據庫內核月報 - 2014/10
- MySQL· 5.7重構·Optimizer Cost Model
- MySQL· 系統限制·text字段數
- MySQL· 捉蟲動態·binlog重放失敗
- MySQL· 捉蟲動態·從庫OOM
- MySQL· 捉蟲動態·崩潰恢復失敗
- MySQL· 功能改進·InnoDB Warmup特性
- MySQL· 文件結構·告別frm文件
- MariaDB· 新鮮特性·ANALYZE statement 語法
- TokuDB· 主備復制·Read Free Replication
- TokuDB· 引擎特性·壓縮
- 數據庫內核月報 - 2014/09
- MySQL· 捉蟲動態·GTID 和 DELAYED
- MySQL· 限制改進·GTID和升級
- MySQL· 捉蟲動態·GTID 和 binlog_checksum
- MySQL· 引擎差異·create_time in status
- MySQL· 參數故事·thread_concurrency
- MySQL· 捉蟲動態·auto_increment
- MariaDB· 性能優化·Extended Keys
- MariaDB·主備復制·CREATE OR REPLACE
- TokuDB· 參數故事·數據安全和性能
- TokuDB· HA方案·TokuDB熱備
- 數據庫內核月報 - 2014/08
- MySQL· 參數故事·timed_mutexes
- MySQL· 參數故事·innodb_flush_log_at_trx_commit
- MySQL· 捉蟲動態·Count(Distinct) ERROR
- MySQL· 捉蟲動態·mysqldump BUFFER OVERFLOW
- MySQL· 捉蟲動態·long semaphore waits
- MariaDB·分支特性·支持大于16K的InnoDB Page Size
- MariaDB·分支特性·FusionIO特性支持
- TokuDB· 性能優化·Bulk Fetch
- TokuDB· 數據結構·Fractal-Trees與LSM-Trees對比
- TokuDB·社區八卦·TokuDB團隊