MySQL 大欄位問題

aoerqileng發表於2022-05-31

開發規範中,一般不讓使用大欄位,大部分關於給出的原因有影響快取,高併發查詢的情況會打滿頻寬,溢位儲存,查詢的時候多了一次指標查詢,在姜老師的書中還看到了一個原因,就是大欄位的dml 會使用悲觀的方式處理,這種對二叉樹加x-latch,會導致併發效能的下降。


姜老師的書中描述是大欄位的插入,更新,刪除會使用悲觀操作,但是我測試的情況是針對insert沒有使用悲觀操作,update是使用了悲觀操作


update的堆疊如下

btr_cur_pessimistic_update(unsigned long flags, btr_cur_t * cursor, big_rec_t ** big_rec, upd_t * update, unsigned long cmpl_info, que_thr_t * thr, mtr_t * mtr) (/root/mysql-5.0.15/innobase/btr/btr0cur.c:1766)
row_upd_clust_rec(upd_node_t * node, dict_index_t * index, que_thr_t * thr, mtr_t * mtr) (/root/mysql-5.0.15/innobase/row/row0upd.c:1530)
row_upd_clust_step(upd_node_t * node, que_thr_t * thr) (/root/mysql-5.0.15/innobase/row/row0upd.c:1742)
row_upd(que_thr_t * thr, upd_node_t * node) (/root/mysql-5.0.15/innobase/row/row0upd.c:1819)
row_upd_step(que_thr_t * thr) (/root/mysql-5.0.15/innobase/row/row0upd.c:1948)
row_update_for_mysql(unsigned char * mysql_rec, row_prebuilt_t * prebuilt) (/root/mysql-5.0.15/innobase/row/row0mysql.c:1386)
ha_innobase::update_row(ha_innobase * const this, const mysql_byte * old_row, mysql_byte * new_row) (/root/mysql-5.0.15/sql/ha_innodb.cc:3622)
mysql_update(THD * thd, TABLE_LIST * table_list, List<Item> & fields, List<Item> & values, COND * conds, uint order_num, ORDER * order, ha_rows limit, enum_duplicates handle_duplicates, bool ignore) (/root/mysql-5.0.15/sql/sql_update.cc:429)
mysql_execute_command(THD * thd) (/root/mysql-5.0.15/sql/sql_parse.cc:3192)
mysql_parse(THD * thd, char * inBuf, uint length) (/root/mysql-5.0.15/sql/sql_parse.cc:5536)
dispatch_command(enum_server_command command, THD * thd, char * packet, unsigned int packet_length) (/root/mysql-5.0.15/sql/sql_parse.cc:1697)
do_command(THD * thd) (/root/mysql-5.0.15/sql/sql_parse.cc:1498)
handle_one_connection(void * arg) (/root/mysql-5.0.15/sql/sql_parse.cc:1143)
libpthread.so.0!start_thread (Unknown Source:0)
libc.so.6!clone (Unknown Source:0)


在更新的時候,先加的s index->lock,然後加了x鎖

堆疊如下

mysqld!btr_cur_search_to_nth_level(dict_index_t*, unsigned long, dtuple_t const*, page_cur_mode_t, unsigned long, btr_cur_t*, unsigned long, char const*, unsigned long, mtr_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/btr/btr0cur.cc:996)
mysqld!btr_pcur_open_with_no_init_func(dict_index_t*, dtuple_t const*, page_cur_mode_t, unsigned long, btr_pcur_t*, unsigned long, char const*, unsigned long, mtr_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/include/btr0pcur.ic:528)
mysqld!btr_pcur_restore_position_func(unsigned long, btr_pcur_t*, char const*, unsigned long, mtr_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/btr/btr0pcur.cc:365)
mysqld!row_upd_clust_rec(unsigned long, upd_node_t*, dict_index_t*, unsigned long*, mem_block_info_t**, que_thr_t*, mtr_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/row/row0upd.cc:2694)
mysqld!row_upd_clust_step(upd_node_t*, que_thr_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/row/row0upd.cc:2957)
mysqld!row_upd(upd_node_t*, que_thr_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/row/row0upd.cc:3054)
mysqld!row_upd_step(que_thr_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/row/row0upd.cc:3200)
mysqld!row_update_for_mysql_using_upd_graph(unsigned char const*, row_prebuilt_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/row/row0mysql.cc:2582)
mysqld!row_update_for_mysql(unsigned char const*, row_prebuilt_t*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/row/row0mysql.cc:2672)
mysqld!ha_innobase::update_row(unsigned char const*, unsigned char*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/handler/ha_innodb.cc:8257)
mysqld!handler::ha_update_row(unsigned char const*, unsigned char*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/handler.cc:8134)
mysqld!mysql_update(THD*, List<Item>&, List<Item>&, unsigned long long, enum_duplicates, unsigned long long*, unsigned long long*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_update.cc:894)
mysqld!Sql_cmd_update::try_single_table_update(THD*, bool*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_update.cc:2906)
mysqld!Sql_cmd_update::execute(THD*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_update.cc:3037)
mysqld!mysql_execute_command(THD*, bool) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:3616)
mysqld!mysql_parse(THD*, Parser_state*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:5584)
mysqld!dispatch_command(THD*, COM_DATA const*, enum_server_command) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:1491)
mysqld!do_command(THD*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/sql_parse.cc:1032)
mysqld!::handle_connection(void *) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/sql/conn_handler/connection_handler_per_thread.cc:313)
mysqld!::pfs_spawn_thread(void *) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/perfschema/pfs.cc:2197)

在btr_cur_search_to_nth_level函式中,執行下面的case分支,加x

switch (latch_mode) {
case BTR_MODIFY_TREE:
        /* Most of delete-intended operations are purging.
        Free blocks and read IO bandwidth should be prior
        for them, when the history list is glowing huge. */
if (lock_intention == BTR_INTENTION_DELETE
&& trx_sys->rseg_history_len > BTR_CUR_FINE_HISTORY_LENGTH
&& buf_get_n_pending_read_ios()) {
mtr_x_lock(dict_index_get_lock(index), mtr);

blob,text 更新都會執行mtr_x_lock(dict_index_get_lock(index), mtr);

即使是更新表中的其他欄位,比如varchar 欄位也會加x鎖,不包含text,blob型別的表更新是不會有的。

所以在規範說明中,可以併發影響這一條。


有興趣學習原始碼的加群一起學習啊 QQ: 700072075

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/25719946/viewspace-2898118/,如需轉載,請註明出處,否則將追究法律責任。

相關文章