亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

Chinaunix

標(biāo)題: mydumper0.23版本的使用和源代碼分析 [打印本頁]

作者: badb0y    時(shí)間: 2011-12-23 01:34
標(biāo)題: mydumper0.23版本的使用和源代碼分析

mydumper是一個(gè)多線程、高性能的數(shù)據(jù)邏輯備份、恢復(fù)的工具,相比MySQL自帶的mysqldump提速不少。我下載了0.23的穩(wěn)定版本,閱讀了源碼并總結(jié)了一些使用的心得。

mysqldump是個(gè)單線程的邏輯備份工具,依次一個(gè)個(gè)導(dǎo)出多個(gè)表,沒有一個(gè)并行的機(jī)制。mydumper彌補(bǔ)了這方面的缺陷可以并行的多線程的從表中讀入數(shù)據(jù)并同時(shí)寫到不同的文件里。項(xiàng)目的作者是由一群在sun、fb、skysql的工程師完成的。類似的工具還有mk-parallel-dump

編譯安裝cmake . make sudo make install 源碼分析

根據(jù)流程圖解釋一下mydumper的工作步驟。

解析參數(shù)
使用glib的g_option_context_parse,比libc里的getopt_long簡單多了。

連接目標(biāo)數(shù)據(jù)庫。

通過show processlist來判斷是否有長查詢,如果有長查詢則退出dump,可以通過–long-query-guard加長時(shí)間,或者使用–kill-long-queries殺掉長查詢。

鎖定myisam表。

針對innodb table開啟事務(wù)。

產(chǎn)生3個(gè)消息隊(duì)列(線程ready隊(duì)列、任務(wù)隊(duì)列、myisam表處理完畢隊(duì)列)。

conf.queue = g_async_queue_new(); conf.ready = g_async_queue_new(); conf.unlock_tables= g_async_queue_new();

產(chǎn)生指定的線程個(gè)數(shù),–threads可以指定,默認(rèn)是4個(gè)。

GThread **threads = g_new(GThread*,num_threads); struct thread_data *td= g_new(struct thread_data, num_threads); for (n=0; n<num_threads; n++) { td[n].conf= &conf; td[n].thread_id= n+1; threads[n] = g_thread_create((GThreadFunc)process_queue,&td[n],TRUE,NULL); g_async_queue_pop(conf.ready); }

dump_database,從DATA_DICTIONARY.TABLES讀取所有表,通過–ignore, –tables-list, regex等過濾條件,產(chǎn)生需要dump的目標(biāo)表列表,分別插入innodb_tables、non_innodb_table、 table_schemas三個(gè)鏈表。

query= g_strdup_printf("SELECT TABLE_NAME, ENGINE, TABLE_TYPE as COMMENT FROM DATA_DICTIONARY.TABLES WHERE TABLE_SCHEMA='%s'", database); .... innodb_tables= g_list_append(innodb_tables, dbt); .... non_innodb_table= g_list_append(non_innodb_table, dbt); .... table_schemas= g_list_append(table_schemas, dbt);

dump non-innodb table 把需要導(dǎo)出myisam表加入到任務(wù)隊(duì)列。

for (non_innodb_table= g_list_first(non_innodb_table); non_innodb_table; non_innodb_table= g_list_next(non_innodb_table)) { dbt= (struct db_table*) non_innodb_table->data; dump_table(conn, dbt->database, dbt->table, &conf, FALSE); g_atomic_int_inc(&non_innodb_table_counter); }

dump innodb table把需要導(dǎo)出innodb表加入任務(wù)隊(duì)列。

for (innodb_tables= g_list_first(innodb_tables); innodb_tables; innodb_tables= g_list_next(innodb_tables)) { dbt= (struct db_table*) innodb_tables->data; dump_table(conn, dbt->database, dbt->table, &conf, TRUE); }

dump schema 把需要導(dǎo)出表結(jié)構(gòu)任務(wù)加入到任務(wù)隊(duì)列。

for (table_schemas= g_list_first(table_schemas); table_schemas; table_schemas= g_list_next(table_schemas)) { dbt= (struct db_table*) table_schemas->data; dump_schema(dbt->database, dbt->table, &conf); g_free(dbt->table); g_free(dbt->database); g_free(dbt); }

典型的生產(chǎn)者(主線程)消費(fèi)者(子線程)模式,子線程會(huì)從任務(wù)隊(duì)列里讀取需要處理的表名字和表類型,再通過select * from table_name 讀入數(shù)據(jù)各自寫入到各自的文件。

for(;;) { .... job=(struct job *)g_async_queue_pop(conf->queue); .... switch (job->type) { case JOB_DUMP: .... dump_table_data_file(thrconn, tj->database, tj->table, tj->where, tj->filename); .... case JOB_DUMP_NON_INNODB: .... dump_table_data_file(thrconn, tj->database, tj->table, tj->where, tj->filename); case JOB_SCHEMA: .... dump_schema_data(thrconn, sj->database, sj->table, sj->filename); }

所有導(dǎo)數(shù)據(jù)的任務(wù)加入任務(wù)隊(duì)列之后,會(huì)再加入讓線程退出的任務(wù),讓線程自然退出。

case JOB_SHUTDOWN: g_message("Thread %d shutting down", td->thread_id); if (thrconn) mysql_close(thrconn); g_free(job); mysql_thread_end(); return NULL; break;

解除myisam表鎖。

等待子線程退出。

使用

導(dǎo)出test database的數(shù)據(jù)

mydumper -h 127.0.0.1 -u root --database test

指定某個(gè)目錄

mydumper -h 127.0.0.1 -u root --outputdir=.

不導(dǎo)出表結(jié)構(gòu)

mydumper -h 127.0.0.1 -u root --no-schema

如果表數(shù)據(jù)是空,還是產(chǎn)生一個(gè)空文件(默認(rèn)無數(shù)據(jù)則只有表結(jié)構(gòu)文件)

mydumper -h 127.0.0.1 -u root --build-empty-files

設(shè)置長查詢的上限,如果存在比這個(gè)還長的查詢則退出mydumper,也可以設(shè)置殺掉這個(gè)長查詢

mydumper -h 127.0.0.1 -u root --long-query-guard 200 --kill-long-queries

設(shè)置要dump的列表–tables-list,不需要設(shè)置db名字,逗號分割

mydumper -h 127.0.0.1 -u root --tables-list=ddd,zzz

通過regex也設(shè)置正則表達(dá),需要設(shè)置db名字

mydumper -h 127.0.0.1 -u root --regex=test.z

把單表分成多個(gè)chunks,這個(gè)后面會(huì)講分割的原理

mydumper -h 127.0.0.1 -u root --rows 10000

過濾某個(gè)引擎的表

mydumper -h 127.0.0.1 -u root -B test --ignore-engines=innodb

詳細(xì)日志

mydumper -h 127.0.0.1 -u root -B test -v 3 幾個(gè)注意點(diǎn)

各自線程都要自己連接到數(shù)據(jù)庫,因?yàn)閘ibmysql是線程不安全的。
因?yàn)閷yisam表有有表鎖,所有先處理myisam表,記錄myisam表個(gè)數(shù),每處理一個(gè)myisam都原子操作數(shù)量減一。并在myisam表都處理完畢后,立即解鎖,盡量減少鎖定的時(shí)間,而不是在導(dǎo)出innodb表數(shù)據(jù)的時(shí)候還在lock myisam表。

main_thread

for (non_innodb_table= g_list_first(non_innodb_table); non_innodb_table; non_innodb_table= g_list_next(non_innodb_table)) { dbt= (struct db_table*) non_innodb_table->data; dump_table(conn, dbt->database, dbt->table, &conf, FALSE); g_atomic_int_inc(&non_innodb_table_counter); }

child_thread

if (g_atomic_int_dec_and_test(&non_innodb_table_counter) && g_atomic_int_get(&non_innodb_done)) { g_async_queue_push(conf->unlock_tables, GINT_TO_POINTER(1)); }

main_thread

g_async_queue_pop(conf.unlock_tables); g_message("Non-InnoDB dump complete, unlocking tables"); mysql_query(conn, "UNLOCK TABLES");

–regex的處理在–tables-list后, 先滿足–tables-list再滿足–regex,如下只會(huì)dump表z1

mydumper -h 127.0.0.1 -u root --regex=test.z1 --outputdir=. --rows=10000 -v 3 -e --tables-list=z2,z1 ** Message: Thread 1 dumping data for `test`.`z1` ** Message: Thread 2 dumping schema for `test`.`z1`

–rows的使用,設(shè)置–rows可以把一個(gè)表分成多個(gè)文件。分塊的原則并不是根據(jù)–rows設(shè)定的行數(shù)來決定生成文件里包含的函數(shù),而是通過rows和表的總行數(shù)計(jì)算出要生成的文件個(gè)數(shù),盡量保證每個(gè)文件的大小一致。

表的總行數(shù)是如何獲得的?
首先mydumper會(huì)選擇一個(gè)索引,順序是pk、uk或者show index from table里Cardinality最高的一個(gè)索引,再通過explain select index from table的rows字段獲得總行數(shù)total_nums(可能不準(zhǔn)確),于是第一個(gè)文件就是從select * from table where index >=1 and index < total_nums/ (int(total_nums/ rows) – 1) + 1。每個(gè)分塊可以分到不同的線程,所以即便同一個(gè)表dump都可以很快加速。

ps:這個(gè)項(xiàng)目大量使用glib(gnome)比較少見,看了一下glib doc覺得glib設(shè)計(jì)的挺好的用起來很方便,否則實(shí)現(xiàn)一個(gè)消息隊(duì)列加多線程還是要幾百行代碼的。接下來要看mydumper0.50的代碼。

作者: hoterran

原文鏈接地址:http://www.hoterran.info/mydumper_usage

myumper源碼下載地址:http://www.mydumper.org/?p=23






歡迎光臨 Chinaunix (http://72891.cn/) Powered by Discuz! X3.2