操作mysql数据库

Mysql数据库管理

强制指定mysql的字符集

修改my.cnf

collation_server=utf8_unicode_ci
character_set_server=utf8
skip-character-set-client-handshake

高负荷请求的一些设置

set-variable = max_connections=500
set-variable = max_connect_errors=10000
set-variable = wait_timeout=300
set-variable = interactive_timeout=30
set-variable = thread_cache=40
set-variable = back_log=500
skip-locking
skip-name-resolve

使用mysqldump备份数据库

mysqldump -u root -p --default-character-set=utf8 --no-create-info {db_name} {table_name} -w"{query_sql}" > backup.sql
  • -u 用户名
  • -p 密码
  • --default-character-set=utf8 (解决乱码, 可以用status来查看你当前数据库默认的是什么字符集来确定是不是要用utf8)
  • --no-create-info (不要create语句, 只要insert, 用来导入数据)
  • -w (指定一张表里的一个符合要求的行, 其实就是where后要跟的条件语句)

数据库还原,直接使用mysql命令:

mysql -u root -p {db_name} < backup.sql

prepare statement

使用prepare statement的好处是比传统的查询方法更快一些, 尤其是做批量的insert, update的时候, 因为它会预处理你的查询语句. 具体请参阅这里.

一个使用prepare statement的例子:

con = mysql_init();
mysql_real_connect(con, ... );
stmt = mysql_stmt_init(con);
mysql_stmt_prepare(stmt, sql, sql_len);
mysql_stmt_bind_param(stmt, bind);
loop {
     select(...);
     mysql_stmt_execute(stmt);
}
mysql_stmt_close(stmt);
mysql_close(conn);

mysql_stmt_bind_param()mysql_stmt_bind_result有一些注意事项, 就是不明确的信息一定要说明. 比如, 当传递int这样固定的类型时候, 不需要指定类型长度, 但传递 char *之类时候就需要了. 另外, 如果传递 unsigned int, 也需要特别说明它是无符号. 例如:

/* Sample1: when query */
unsigned int ip;
char phone[PHONE_SIZE];
int phone_len = strlen(phone);

MYSQL_BIND bind[2];
memset(bind, 0, sizeof(bind));

bind[0].buffer_type = MYSQL_TYPE_STRING;
bind[0].buffer = &phone;
bind[0].buffer_length = PHONE_SIZE; /* max length */
bind[0].is_null = 0;
bind[0].length = &phone_len;        /* actually length, can be omitted */

bind[1].buffer_type= MYSQL_TYPE_LONG;
bind[1].buffer= &ip;
bind[1].is_null= 0;
bind[1].length= 0;
bind[1].is_unsigned = TRUE;          /* must announced */

mysql_stmt_bind_param(stmt, bind);

/* Sample2: when fetch */
char address[ADDR_SIZE];

MYSQL_BIND bine[1];
my_bool is_null[1];
unsigned long length[1];
my_bool error[1];

memset(bind, 0, sizeof(bine));

bind[0].buffer_type = MYSQL_TYPE_STRING;
bind[0].buffer = (char *)address;
bind[0].buffer_length = ADDR_SIZE;
bind[0].is_null = &is_null[0];
bind[0].length = &length[0];
bind[0].error = &error[0];

/* bind the result buffers */
mysql_stmt_bind_result(stmt, bine);

如果你在使用MYSQL++库的话,遗憾的是它目前还不支持prepare statement,虽然在wishlist里面已经很久了。这里可以推荐使用mysql自己出的一套库Connector C++,支持JDBC 3.0 API,并且支持prepare statement,不过暂时该产品还在preview阶段。

关于超时

如果两次数据库操作之间间隔的时间过长, 则中途数据库连接会超时, 解决办法是:

  • 自己维护连接池, 考虑使用 stl::set
  • 使用一些有连接池的库, 比如 MYSQL++
  • 在my.cnf中延长wait_timeout
  • 设置MYSQL_OPT_RECONNECT, 这个选项在mysql5.0.13后默认禁用了, 有副作用.

      #ifdef MYSQL_OPT_RECONNECT
      my_bool ifreconn=1;
      if(mysql_options(con,MYSQL_OPT_RECONNECT,&ifreconn)){ //since 5.0.13
          //mysql_errno(con);
          //...do sth else
      }
      #else
      con->reconnect=1;
      #endif
    

一些链接