~ubuntu-branches/ubuntu/karmic/mysql-dfsg-5.1/karmic

« back to all changes in this revision

Viewing changes to sql/log.cc

  • Committer: Bazaar Package Importer
  • Author(s): Mathias Gug
  • Date: 2009-02-10 16:42:05 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20090210164205-ej41ocvm4z1s14nq
Tags: 5.1.31-1ubuntu1
* Merge from debian experimental, remaining changes: 
  - debian/mysql-server-5.1.config: ask for MySQL root password at priority
    high instead of medium so that the password prompt is seen on a default
    install. (LP: #319843)
  - debian/control: 
    + Don't build mysql-server, mysql-client, mysql-common and 
      libmysqlclient15-dev binary packages since they're still provided 
      by mysql-dfsg-5.0.
    + Rename libmysqlclient-dev package to libmysqlclient16-dev (LP: #316280).
      Make it conflict with libmysqlclient15-dev.
    + Make mysql-{client,server}-5.1 packages conflict and
      replace mysql-{client,server}-5.0, but not provide 
      mysql-{client,server}.
    + Depend on a specific version of mysql-common rather than the src 
      version of mysql-dfsg-5.1 since mysql-common is currently part of
      mysql-dfsg-5.0.
  - debian/rules: added -fno-strict-aliasing to CFLAGS to get
    around mysql testsuite build failures.
* debian/patches/92_ssl_test_cert.dpatch: certificate expiration in 
  test suite (LP: #323755).
* Dropped changes:
  - all of the changes made to support both 5.0 and 5.1 installed at the
    same time have been dropped now that amarok doesn't depend on
    mysql-server-5.1 anymore.

Show diffs side-by-side

added added

removed removed

Lines of Context:
207
207
      truncate(0);
208
208
    before_stmt_pos= MY_OFF_T_UNDEF;
209
209
    trans_log.end_of_file= max_binlog_cache_size;
 
210
    DBUG_ASSERT(empty());
210
211
  }
211
212
 
212
213
  Rows_log_event *pending() const
1377
1378
                      FLAGSTR(thd->options, OPTION_NOT_AUTOCOMMIT),
1378
1379
                      FLAGSTR(thd->options, OPTION_BEGIN)));
1379
1380
 
1380
 
  thd->binlog_flush_pending_rows_event(TRUE);
1381
 
 
1382
1381
  /*
1383
1382
    NULL denotes ROLLBACK with nothing to replicate: i.e., rollback of
1384
1383
    only transactional tables.  If the transaction contain changes to
1387
1386
  */
1388
1387
  if (end_ev != NULL)
1389
1388
  {
 
1389
    thd->binlog_flush_pending_rows_event(TRUE);
1390
1390
    /*
1391
1391
      Doing a commit or a rollback including non-transactional tables,
1392
1392
      i.e., ending a transaction where we might write the transaction
1435
1435
    mysql_bin_log.update_table_map_version();
1436
1436
  }
1437
1437
 
 
1438
  DBUG_ASSERT(thd->binlog_get_pending_rows_event() == NULL);
1438
1439
  DBUG_RETURN(error);
1439
1440
}
1440
1441
 
1466
1467
*/
1467
1468
static int binlog_commit(handlerton *hton, THD *thd, bool all)
1468
1469
{
 
1470
  int error= 0;
1469
1471
  DBUG_ENTER("binlog_commit");
1470
1472
  binlog_trx_data *const trx_data=
1471
1473
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
1478
1480
  }
1479
1481
 
1480
1482
  /*
1481
 
    Decision table for committing a transaction. The top part, the
1482
 
    *conditions* represent different cases that can occur, and hte
1483
 
    bottom part, the *actions*, represent what should be done in that
1484
 
    particular case.
1485
 
 
1486
 
    Real transaction        'all' was true
1487
 
 
1488
 
    Statement in cache      There were at least one statement in the
1489
 
                            transaction cache
1490
 
 
1491
 
    In transaction          We are inside a transaction
1492
 
 
1493
 
    Stmt modified non-trans The statement being committed modified a
1494
 
                            non-transactional table
1495
 
 
1496
 
    All modified non-trans  Some statement before this one in the
1497
 
                            transaction modified a non-transactional
1498
 
                            table
1499
 
 
1500
 
 
1501
 
    =============================  = = = = = = = = = = = = = = = =
1502
 
    Real transaction               N N N N N N N N N N N N N N N N
1503
 
    Statement in cache             N N N N N N N N Y Y Y Y Y Y Y Y
1504
 
    In transaction                 N N N N Y Y Y Y N N N N Y Y Y Y
1505
 
    Stmt modified non-trans        N N Y Y N N Y Y N N Y Y N N Y Y
1506
 
    All modified non-trans         N Y N Y N Y N Y N Y N Y N Y N Y
1507
 
 
1508
 
    Action: (C)ommit/(A)ccumulate  C C - C A C - C - - - - A A - A
1509
 
    =============================  = = = = = = = = = = = = = = = =
1510
 
 
1511
 
 
1512
 
    =============================  = = = = = = = = = = = = = = = =
1513
 
    Real transaction               Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
1514
 
    Statement in cache             N N N N N N N N Y Y Y Y Y Y Y Y
1515
 
    In transaction                 N N N N Y Y Y Y N N N N Y Y Y Y
1516
 
    Stmt modified non-trans        N N Y Y N N Y Y N N Y Y N N Y Y
1517
 
    All modified non-trans         N Y N Y N Y N Y N Y N Y N Y N Y
1518
 
 
1519
 
    (C)ommit/(A)ccumulate/(-)      - - - - C C - C - - - - C C - C
1520
 
    =============================  = = = = = = = = = = = = = = = =
1521
 
 
1522
 
    In other words, we commit the transaction if and only if both of
1523
 
    the following are true:
1524
 
     - We are not in a transaction and committing a statement
1525
 
 
1526
 
     - We are in a transaction and one (or more) of the following are
1527
 
       true:
1528
 
 
1529
 
       - A full transaction is committed
1530
 
 
1531
 
         OR
1532
 
 
1533
 
       - A non-transactional statement is committed and there is
1534
 
         no statement cached
 
1483
    We commit the transaction if:
 
1484
 
 
1485
     - We are not in a transaction and committing a statement, or
 
1486
 
 
1487
     - We are in a transaction and a full transaction is committed
1535
1488
 
1536
1489
    Otherwise, we accumulate the statement
1537
1490
  */
1544
1497
              YESNO(in_transaction),
1545
1498
              YESNO(thd->transaction.all.modified_non_trans_table),
1546
1499
              YESNO(thd->transaction.stmt.modified_non_trans_table)));
1547
 
  if (in_transaction &&
1548
 
      (all ||
1549
 
       (!trx_data->at_least_one_stmt &&
1550
 
        thd->transaction.stmt.modified_non_trans_table)) ||
1551
 
      !in_transaction && !all)
 
1500
  if (!in_transaction || all)
1552
1501
  {
1553
1502
    Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE);
1554
1503
    qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE)
1555
 
    int error= binlog_end_trans(thd, trx_data, &qev, all);
1556
 
    DBUG_RETURN(error);
 
1504
    error= binlog_end_trans(thd, trx_data, &qev, all);
 
1505
    goto end;
1557
1506
  }
1558
 
  DBUG_RETURN(0);
 
1507
 
 
1508
end:
 
1509
  if (!all)
 
1510
    trx_data->before_stmt_pos = MY_OFF_T_UNDEF; // part of the stmt commit
 
1511
  DBUG_RETURN(error);
1559
1512
}
1560
1513
 
1561
1514
/**
1615
1568
     */
1616
1569
    error= binlog_end_trans(thd, trx_data, 0, all);
1617
1570
  }
 
1571
  if (!all)
 
1572
    trx_data->before_stmt_pos = MY_OFF_T_UNDEF; // part of the stmt rollback
1618
1573
  DBUG_RETURN(error);
1619
1574
}
1620
1575
 
2359
2314
  */
2360
2315
  index_file_name[0] = 0;
2361
2316
  bzero((char*) &index_file, sizeof(index_file));
 
2317
  bzero((char*) &purge_temp, sizeof(purge_temp));
2362
2318
}
2363
2319
 
2364
2320
/* this is called only once */
2953
2909
int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included)
2954
2910
{
2955
2911
  int error;
 
2912
  char *to_purge_if_included= NULL;
2956
2913
  DBUG_ENTER("purge_first_log");
2957
2914
 
2958
2915
  DBUG_ASSERT(is_open());
2960
2917
  DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->event_relay_log_name));
2961
2918
 
2962
2919
  pthread_mutex_lock(&LOCK_index);
2963
 
  pthread_mutex_lock(&rli->log_space_lock);
2964
 
  rli->relay_log.purge_logs(rli->group_relay_log_name, included,
2965
 
                            0, 0, &rli->log_space_total);
2966
 
  // Tell the I/O thread to take the relay_log_space_limit into account
2967
 
  rli->ignore_log_space_limit= 0;
2968
 
  pthread_mutex_unlock(&rli->log_space_lock);
 
2920
  to_purge_if_included= my_strdup(rli->group_relay_log_name, MYF(0));
2969
2921
 
2970
2922
  /*
2971
 
    Ok to broadcast after the critical region as there is no risk of
2972
 
    the mutex being destroyed by this thread later - this helps save
2973
 
    context switches
2974
 
  */
2975
 
  pthread_cond_broadcast(&rli->log_space_cond);
2976
 
  
2977
 
  /*
2978
2923
    Read the next log file name from the index file and pass it back to
2979
 
    the caller
2980
 
    If included is true, we want the first relay log;
2981
 
    otherwise we want the one after event_relay_log_name.
 
2924
    the caller.
2982
2925
  */
2983
 
  if ((included && (error=find_log_pos(&rli->linfo, NullS, 0))) ||
2984
 
      (!included &&
2985
 
       ((error=find_log_pos(&rli->linfo, rli->event_relay_log_name, 0)) ||
2986
 
        (error=find_next_log(&rli->linfo, 0)))))
 
2926
  if((error=find_log_pos(&rli->linfo, rli->event_relay_log_name, 0)) || 
 
2927
     (error=find_next_log(&rli->linfo, 0)))
2987
2928
  {
2988
2929
    char buff[22];
2989
2930
    sql_print_error("next log error: %d  offset: %s  log: %s included: %d",
2990
2931
                    error,
2991
2932
                    llstr(rli->linfo.index_file_offset,buff),
2992
 
                    rli->group_relay_log_name,
 
2933
                    rli->event_relay_log_name,
2993
2934
                    included);
2994
2935
    goto err;
2995
2936
  }
3017
2958
  /* Store where we are in the new file for the execution thread */
3018
2959
  flush_relay_log_info(rli);
3019
2960
 
 
2961
  DBUG_EXECUTE_IF("crash_before_purge_logs", abort(););
 
2962
 
 
2963
  pthread_mutex_lock(&rli->log_space_lock);
 
2964
  rli->relay_log.purge_logs(to_purge_if_included, included,
 
2965
                            0, 0, &rli->log_space_total);
 
2966
  // Tell the I/O thread to take the relay_log_space_limit into account
 
2967
  rli->ignore_log_space_limit= 0;
 
2968
  pthread_mutex_unlock(&rli->log_space_lock);
 
2969
 
 
2970
  /*
 
2971
    Ok to broadcast after the critical region as there is no risk of
 
2972
    the mutex being destroyed by this thread later - this helps save
 
2973
    context switches
 
2974
  */
 
2975
  pthread_cond_broadcast(&rli->log_space_cond);
 
2976
 
 
2977
  /*
 
2978
   * Need to update the log pos because purge logs has been called 
 
2979
   * after fetching initially the log pos at the begining of the method.
 
2980
   */
 
2981
  if((error=find_log_pos(&rli->linfo, rli->event_relay_log_name, 0)))
 
2982
  {
 
2983
    char buff[22];
 
2984
    sql_print_error("next log error: %d  offset: %s  log: %s included: %d",
 
2985
                    error,
 
2986
                    llstr(rli->linfo.index_file_offset,buff),
 
2987
                    rli->group_relay_log_name,
 
2988
                    included);
 
2989
    goto err;
 
2990
  }
 
2991
 
 
2992
  /* If included was passed, rli->linfo should be the first entry. */
 
2993
  DBUG_ASSERT(!included || rli->linfo.index_file_start_offset == 0);
 
2994
 
3020
2995
err:
 
2996
  my_free(to_purge_if_included, MYF(0));
3021
2997
  pthread_mutex_unlock(&LOCK_index);
3022
2998
  DBUG_RETURN(error);
3023
2999
}
3068
3044
                          ulonglong *decrease_log_space)
3069
3045
{
3070
3046
  int error;
3071
 
  int ret = 0;
3072
3047
  bool exit_loop= 0;
3073
3048
  LOG_INFO log_info;
3074
3049
  THD *thd= current_thd;
3077
3052
 
3078
3053
  if (need_mutex)
3079
3054
    pthread_mutex_lock(&LOCK_index);
3080
 
  if ((error=find_log_pos(&log_info, to_log, 0 /*no mutex*/)))
 
3055
  if ((error=find_log_pos(&log_info, to_log, 0 /*no mutex*/))) 
 
3056
  {
 
3057
    sql_print_error("MYSQL_LOG::purge_logs was called with file %s not "
 
3058
                    "listed in the index.", to_log);
3081
3059
    goto err;
 
3060
  }
 
3061
 
 
3062
  /*
 
3063
    For crash recovery reasons the index needs to be updated before
 
3064
    any files are deleted. Move files to be deleted into a temp file
 
3065
    to be processed after the index is updated.
 
3066
  */
 
3067
  if (!my_b_inited(&purge_temp))
 
3068
  {
 
3069
    if ((error=open_cached_file(&purge_temp, mysql_tmpdir, TEMP_PREFIX,
 
3070
                                DISK_BUFFER_SIZE, MYF(MY_WME))))
 
3071
    {
 
3072
      sql_print_error("MYSQL_LOG::purge_logs failed to open purge_temp");
 
3073
      goto err;
 
3074
    }
 
3075
  }
 
3076
  else
 
3077
  {
 
3078
    if ((error=reinit_io_cache(&purge_temp, WRITE_CACHE, 0, 0, 1)))
 
3079
    {
 
3080
      sql_print_error("MYSQL_LOG::purge_logs failed to reinit purge_temp "
 
3081
                      "for write");
 
3082
      goto err;
 
3083
    }
 
3084
  }
3082
3085
 
3083
3086
  /*
3084
3087
    File name exists in index file; delete until we find this file
3089
3092
  while ((strcmp(to_log,log_info.log_file_name) || (exit_loop=included)) &&
3090
3093
         !log_in_use(log_info.log_file_name))
3091
3094
  {
 
3095
    if ((error=my_b_write(&purge_temp, (const uchar*)log_info.log_file_name,
 
3096
                          strlen(log_info.log_file_name))) ||
 
3097
        (error=my_b_write(&purge_temp, (const uchar*)"\n", 1)))
 
3098
    {
 
3099
      sql_print_error("MYSQL_LOG::purge_logs failed to copy %s to purge_temp",
 
3100
                      log_info.log_file_name);
 
3101
      goto err;
 
3102
    }
 
3103
 
 
3104
    if (find_next_log(&log_info, 0) || exit_loop)
 
3105
      break;
 
3106
 }
 
3107
 
 
3108
  /* We know how many files to delete. Update index file. */
 
3109
  if ((error=update_log_index(&log_info, need_update_threads)))
 
3110
  {
 
3111
    sql_print_error("MSYQL_LOG::purge_logs failed to update the index file");
 
3112
    goto err;
 
3113
  }
 
3114
 
 
3115
  DBUG_EXECUTE_IF("crash_after_update_index", abort(););
 
3116
 
 
3117
  /* Switch purge_temp for read. */
 
3118
  if ((error=reinit_io_cache(&purge_temp, READ_CACHE, 0, 0, 0)))
 
3119
  {
 
3120
    sql_print_error("MSYQL_LOG::purge_logs failed to reinit purge_temp "
 
3121
                    "for read");
 
3122
    goto err;
 
3123
  }
 
3124
 
 
3125
  /* Read each entry from purge_temp and delete the file. */
 
3126
  for (;;)
 
3127
  {
 
3128
    uint length;
 
3129
 
 
3130
    if ((length=my_b_gets(&purge_temp, log_info.log_file_name,
 
3131
                          FN_REFLEN)) <= 1)
 
3132
    {
 
3133
      if (purge_temp.error)
 
3134
      {
 
3135
        error= purge_temp.error;
 
3136
        sql_print_error("MSYQL_LOG::purge_logs error %d reading from "
 
3137
                        "purge_temp", error);
 
3138
        goto err;
 
3139
      }
 
3140
 
 
3141
      /* Reached EOF */
 
3142
      break;
 
3143
    }
 
3144
 
 
3145
    /* Get rid of the trailing '\n' */
 
3146
    log_info.log_file_name[length-1]= 0;
 
3147
 
 
3148
    ha_binlog_index_purge_file(current_thd, log_info.log_file_name);
 
3149
 
3092
3150
    MY_STAT s;
3093
3151
    if (!my_stat(log_info.log_file_name, &s, MYF(0)))
3094
3152
    {
3189
3247
        }
3190
3248
      }
3191
3249
    }
3192
 
 
3193
 
    ha_binlog_index_purge_file(current_thd, log_info.log_file_name);
3194
 
 
3195
 
    if (find_next_log(&log_info, 0) || exit_loop)
3196
 
      break;
3197
 
  }
3198
 
  
3199
 
  /*
3200
 
    If we get killed -9 here, the sysadmin would have to edit
3201
 
    the log index file after restart - otherwise, this should be safe
3202
 
  */
3203
 
  error= update_log_index(&log_info, need_update_threads);
3204
 
  if (error == 0) {
3205
 
    error = ret;
3206
3250
  }
3207
3251
 
3208
3252
err:
 
3253
  close_cached_file(&purge_temp);
3209
3254
  if (need_mutex)
3210
3255
    pthread_mutex_unlock(&LOCK_index);
3211
3256
  DBUG_RETURN(error);
3216
3261
  index file.
3217
3262
 
3218
3263
  @param thd            Thread pointer
3219
 
  @param before_date    Delete all log files before given date.
 
3264
  @param purge_time     Delete all log files before given date.
3220
3265
 
3221
3266
  @note
3222
3267
    If any of the logs before the deleted one is in use,
3233
3278
int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time)
3234
3279
{
3235
3280
  int error;
 
3281
  char to_log[FN_REFLEN];
3236
3282
  LOG_INFO log_info;
3237
3283
  MY_STAT stat_area;
3238
3284
  THD *thd= current_thd;
3240
3286
  DBUG_ENTER("purge_logs_before_date");
3241
3287
 
3242
3288
  pthread_mutex_lock(&LOCK_index);
 
3289
  to_log[0]= 0;
3243
3290
 
3244
 
  /*
3245
 
    Delete until we find curren file
3246
 
    or a file that is used or a file
3247
 
    that is older than purge_time.
3248
 
  */
3249
3291
  if ((error=find_log_pos(&log_info, NullS, 0 /*no mutex*/)))
3250
3292
    goto err;
3251
3293
 
3295
3337
    }
3296
3338
    else
3297
3339
    {
3298
 
      if (stat_area.st_mtime >= purge_time)
 
3340
      if (stat_area.st_mtime < purge_time) 
 
3341
        strmake(to_log, 
 
3342
                log_info.log_file_name, 
 
3343
                sizeof(log_info.log_file_name));
 
3344
      else
3299
3345
        break;
3300
 
      if (my_delete(log_info.log_file_name, MYF(0)))
3301
 
      {
3302
 
        if (my_errno == ENOENT) 
3303
 
        {
3304
 
          /* It's not fatal even if we can't delete a log file */
3305
 
          if (thd)
3306
 
          {
3307
 
            push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
3308
 
                                ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
3309
 
                                log_info.log_file_name);
3310
 
          }
3311
 
          sql_print_information("Failed to delete file '%s'",
3312
 
                                log_info.log_file_name);
3313
 
          my_errno= 0;
3314
 
        }
3315
 
        else
3316
 
        {
3317
 
          if (thd)
3318
 
          {
3319
 
            push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
3320
 
                                ER_BINLOG_PURGE_FATAL_ERR,
3321
 
                                "a problem with deleting %s; "
3322
 
                                "consider examining correspondence "
3323
 
                                "of your binlog index file "
3324
 
                                "to the actual binlog files",
3325
 
                                log_info.log_file_name);
3326
 
          }
3327
 
          else
3328
 
          {
3329
 
            sql_print_information("Failed to delete log file '%s'",
3330
 
                                  log_info.log_file_name); 
3331
 
          }
3332
 
          error= LOG_INFO_FATAL;
3333
 
          goto err;
3334
 
        }
3335
 
      }
3336
 
      ha_binlog_index_purge_file(current_thd, log_info.log_file_name);
3337
3346
    }
3338
3347
    if (find_next_log(&log_info, 0))
3339
3348
      break;
3340
3349
  }
3341
3350
 
3342
 
  /*
3343
 
    If we get killed -9 here, the sysadmin would have to edit
3344
 
    the log index file after restart - otherwise, this should be safe
3345
 
  */
3346
 
  error= update_log_index(&log_info, 1);
 
3351
  error= (to_log[0] ? purge_logs(to_log, 1, 0, 1, (ulonglong *) 0) : 0);
3347
3352
 
3348
3353
err:
3349
3354
  pthread_mutex_unlock(&LOCK_index);