create table t1(id int);

    insert into t1 values(1)

    略过建立连接,从 mysql_parse() 开始分析

    进入 mysql_execute_command()

    1. /* ...... */
    2. case SQLCOM_INSERT:
    3. {
    4. /* 检查权限 */
    5. if ((res= insert_precheck(thd, all_tables)))
    6. break;
    7. /* 执行insert */
    8. res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
    9. lex->update_list, lex->value_list,
    10. lex->duplicates, lex->ignore);
    11. /* 提交或者回滚事务 */
    12. if (!res)
    13. {
    14. trans_commit_stmt(thd);
    15. trans_commit(thd);
    16. thd->trx_end_by_hint= TRUE;
    17. }
    18. else if (res)
    19. {
    20. trans_rollback_stmt(thd);
    21. trans_rollback(thd);
    22. thd->trx_end_by_hint= TRUE;
    23. }
    1. bool mysql_insert(THD *thd,TABLE_LIST *table_list,
    2. List<Item> &fields, /* insert 的字段 */
    3. List<List_item> &values_list, /* insert 的值 */
    4. List<Item> &update_fields,
    5. List<Item> &update_values,
    6. enum_duplicates duplic,
    7. bool ignore)
    8. {
    9. /*对每条记录调用 write_record */
    10. while ((values= its++))
    11. {
    12. if (lock_type == TL_WRITE_DELAYED)
    13. {
    14. LEX_STRING const st_query = { query, thd->query_length() };
    15. DEBUG_SYNC(thd, "before_write_delayed");
    16. /* insert delay */
    17. error= write_delayed(thd, table, st_query, log_on, &info);
    18. DEBUG_SYNC(thd, "after_write_delayed");
    19. query=0;
    20. }
    21. else
    22. /* normal insert */
    23. error= write_record(thd, table, &info, &update);
    24. }
    25. /*
    26. 这里还有
    27. thd->binlog_query()写binlog
    28. my_ok()返回ok报文,ok报文中包含影响行数
    29. */

    进入 write_record

    1. /*
    2. COPY_INFO *info 用来处理唯一键冲突,记录影响行数
    3. COPY_INFO *update 处理 INSERT ON DUPLICATE KEY UPDATE 相关信息
    4. */
    5. {
    6. if (duplicate_handling == DUP_REPLACE || duplicate_handling == DUP_UPDATE)
    7. {
    8. /* 处理 INSERT ON DUPLICATE KEY UPDATE 等复杂情况 */
    9. }
    10. /* 调用存储引擎的接口 */
    11. else if ((error=table->file->ha_write_row(table->record[0])))
    12. {
    13. DEBUG_SYNC(thd, "write_row_noreplace");
    14. if (!ignore_errors ||
    15. table->file->is_fatal_error(error, HA_CHECK_DUP))
    16. goto err;
    17. table->file->restore_auto_increment(prev_insert_id);
    18. goto ok_or_after_trg_err;
    19. }
    20. }

    进入ha_write_row、write_row

    进入引擎层,这里是innodb引擎,handler对应ha_innobase 插入的表信息保存在handler中

    1. int
    2. ha_innobase::write_row(
    3. /*===================*/
    4. uchar* record) /*!< in: a row in MySQL format */
    5. {
    6. error = row_insert_for_mysql((byte*) record, prebuilt);
    7. }
    1. UNIV_INTERN
    2. dberr_t
    3. row_insert_for_mysql(
    4. /*=================*/
    5. byte* mysql_rec, /*!< in: row in the MySQL format */
    6. row_prebuilt_t* prebuilt) /*!< in: prebuilt struct in MySQL
    7. handle */
    8. {
    9. /*记录格式从MySQL转换成InnoDB*/
    10. row_mysql_convert_row_to_innobase(node->row, prebuilt, mysql_rec);
    11. thr->run_node = node;
    12. thr->prev_node = node;
    13. /*插入记录*/
    14. row_ins_step(thr);
    15. }
    1. UNIV_INTERN
    2. que_thr_t*
    3. row_ins_step(
    4. /*=========*/
    5. que_thr_t* thr) /*!< in: query thread */
    6. {
    7. /*给表加IX锁*/
    8. err = lock_table(0, node->table, LOCK_IX, thr);
    9. /*插入记录*/
    10. err = row_ins(node, thr);
    11. }

    InnoDB表是基于B+树的索引组织表

    row_id分配逻辑在row_ins中,这里不详细展开

    插入单个索引项

    1. static __attribute__((nonnull, warn_unused_result))
    2. dberr_t
    3. row_ins_index_entry_step(
    4. /*=====================*/
    5. ins_node_t* node, /*!< in: row insert node */
    6. que_thr_t* thr) /*!< in: query thread */
    7. {
    8. dberr_t err;
    9. row_ins_index_entry_set_vals(node->index, node->entry, node->row);
    10. /*插入索引项*/
    11. err = row_ins_index_entry(node->index, node->entry, thr);
    12. return(err);
    13. }
    1. static
    2. dberr_t
    3. row_ins_index_entry(
    4. /*================*/
    5. dict_index_t* index, /*!< in: index */
    6. dtuple_t* entry, /*!< in/out: index entry to insert */
    7. que_thr_t* thr) /*!< in: query thread */
    8. {
    9. if (dict_index_is_clust(index)) {
    10. /* 插入聚集索引 */
    11. return(row_ins_clust_index_entry(index, entry, thr, 0));
    12. } else {
    13. /* 插入二级索引 */
    14. return(row_ins_sec_index_entry(index, entry, thr));
    15. }
    16. }

    row_ins_clust_index_entry 和 row_ins_sec_index_entry 函数结构类似,只分析插入聚集索引

    1. UNIV_INTERN
    2. dberr_t
    3. row_ins_clust_index_entry(
    4. /*======================*/
    5. dict_index_t* index, /*!< in: clustered index */
    6. dtuple_t* entry, /*!< in/out: index entry to insert */
    7. que_thr_t* thr, /*!< in: query thread */
    8. ulint n_ext) /*!< in: number of externally stored columns */
    9. {
    10. if (UT_LIST_GET_FIRST(index->table->foreign_list)) {
    11. err = row_ins_check_foreign_constraints(
    12. index->table, index, entry, thr);
    13. if (err != DB_SUCCESS) {
    14. return(err);
    15. }
    16. }
    17. /* flush log,make checkpoint(如果需要) */
    18. log_free_check();
    19. /* 先尝试乐观插入,修改叶子节点 BTR_MODIFY_LEAF */
    20. err = row_ins_clust_index_entry_low(
    21. 0, BTR_MODIFY_LEAF, index, n_uniq, entry, n_ext, thr,
    22. &page_no, &modify_clock);
    23. if (err != DB_FAIL) {
    24. DEBUG_SYNC_C("row_ins_clust_index_entry_leaf_after");
    25. return(err);
    26. }
    27. /* flush log,make checkpoint(如果需要) */
    28. log_free_check();
    29. /* 乐观插入失败,尝试悲观插入 BTR_MODIFY_TREE */
    30. return(row_ins_clust_index_entry_low(
    31. 0, BTR_MODIFY_TREE, index, n_uniq, entry, n_ext, thr,
    32. &page_no, &modify_clock));

    row_ins_clust_index_entry_low 和 row_ins_sec_index_entry_low 函数结构类似,只分析插入聚集索引