Chinaunix首页 | 论坛 | 博客
  • 博客访问: 476917
  • 博文数量: 99
  • 博客积分: 3621
  • 博客等级: 中校
  • 技术积分: 1089
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-22 16:29
文章存档

2012年(21)

2011年(28)

2010年(50)

分类: Mysql/postgreSQL

2011-05-27 16:14:04

过程分析:
今天在分析慢查询日志的时候,发现一些这样的语句:
#=======================================================================================
# Query_time: 2.652960  Lock_time: 0.000000 Rows_sent: 1309590  Rows_examined: 1309590
SET timestamp=1306474204;
SELECT /*!40001 SQL_NO_CACHE */ * FROM `categorylinks`;
#=======================================================================================
查询这个表的所有记录。在程序里面不可能有这样的业务存在。然后看了下产生的时间,是00:30,正是备份数据库的时间。莫非是备份数据库时的查询?

打开备份文件,看下对每个表的备份流程是怎么样的
#========================================================================================
1:LOCK TABLES `myt` WRITE;
2:/*!40000 ALTER TABLE `myt` DISABLE KEYS */;
3:INSERT INTO `myt` VALUES ('table ™ name'),('table ? name'),('table ™ name'),('table ™ name');
4:/*!40000 ALTER TABLE `myt` ENABLE KEYS */;
5:UNLOCK TABLES;
#=========================================================================================
mysqldump程序能够得到values里的值,肯定是查了整个表的,然后再在程序里拼好,形成insert语句。
在每个表的备份里面,都有“LOCK TABLES”,看看源码里是怎么操作的:
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
if (opt_lock)                     #是否锁表的参数,就是mysqldump --help 看到的 --add-locks         Add locks around INSERT statements.
    {
      fprintf(md_result_file,"LOCK TABLES %s WRITE;\n", opt_quoted_table);   #如果是,打印lock table
      check_io(md_result_file);   #检查文件写入情况,每个地方都有,如果写入文件失败,就退出错误。
    }
    /* Moved disable keys to after lock per bug 15977 */
    if (opt_disable_keys)         #这里就是备份文件的第2行了
    {
      fprintf(md_result_file, "/*!40000 ALTER TABLE %s DISABLE KEYS */;\n",
          opt_quoted_table);
      check_io(md_result_file);
    }
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
主要备份的数据是在第三行,看看是怎么处理的:
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/*
      If write_data is true, then we build up insert statements for
      the table's data. Note: in subsequent lines of code, this test
      will have to be performed each time we are appending to
      insert_pat.
    */
    if (write_data)             #重点来了,看它怎么样拼SQL
    {
      if (opt_replace_into)
        dynstr_append_checked(&insert_pat, "REPLACE ");  #这些根据参数决定用INSERT ,REPLACE等插入方法
      else
        dynstr_append_checked(&insert_pat, "INSERT ");
      dynstr_append_checked(&insert_pat, insert_option);
      dynstr_append_checked(&insert_pat, "INTO ");
      dynstr_append_checked(&insert_pat, opt_quoted_table);
      if (complete_insert)
      {
        dynstr_append_checked(&insert_pat, " (");     #左边括号出现了
      }
      else
      {
        dynstr_append_checked(&insert_pat, " VALUES ");
        if (!extended_insert)
          dynstr_append_checked(&insert_pat, "(");
      }
    }

    while ((row= mysql_fetch_row(result)))    #在这里循环select * from tbname里的记录了
    {
      if (complete_insert)
      {
        if (init)
        {
          dynstr_append_checked(&insert_pat, ", "); #还在拼SQL
        }
        init=1;
        dynstr_append_checked(&insert_pat,
                      quote_name(row[SHOW_FIELDNAME], name_buff, 0));
      }
    }
    num_fields= mysql_num_rows(result);
    mysql_free_result(result);
  }
  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
      if (extended_insert)
      {
        ulong row_length;
        dynstr_append_checked(&extended_row,")");   #反括号在这里出现了

#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
代码写得很复杂,我断章取义挑出其中一部分看看,可能有地方不对,但是可以确定的一点是,mysqldump程序是要select * from tbname去获取数据的,而且如果表很大
这个查询时间很长的话,是会被记录到慢查询日志里的。

连接HOST和DB的函数
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/*
  db_connect -- connects to the host and selects DB.
*/

static int connect_to_db(char *host, char *user,char *passwd)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
查询表数据的函数
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * FROM ");
    dynstr_append_checked(&query_string, result_table);
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

mysqldump的大概流程整理如下:
1:连接上数据库,根据输入的账户,密码,IP
2:进入INFORMATION_SCHEMA库,获取要备份的数据库的信息,包含存储过程,视图,表
3:进入INFORMATION_SCHEMA库,获取每个表的字段名称,字段类型等信息
4:查询每个表的数据,select SQL_NO_CACHE from tbname
5:拼SQL
6:写入备份文件

阅读(1327) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~