~ubuntu-branches/ubuntu/natty/mysql-5.1/natty

« back to all changes in this revision

Viewing changes to storage/innodb_plugin/dict/dict0dict.c

Tags: 5.1.54-1ubuntu1
* Synchronize from Debian Experimental:
* Merge from debian unstable:
  + debian/control:
     * Update maintainer according to spec.
     * Move section from "misc" to "database".
     * Added libmysqlclient16-dev an empty transitional package. 
     * Added mysql-client-core-5.1 package.
     * Suggest mailx for mysql-server-5.1
     * Add mysql-testsuite package so you can run the testsuite seperately.
  + debian/additions/my.cnf:
    * Remove language options. Error message files are located in a different directory in Mysql
      5.0. Setting the language option to use /usr/share/mysql/english breaks Mysql 5.0. Both 5.0
      and 5.1 use a different value that works. (LP: #316974)
  + Add apparmor profile:
    + debian/apparmor-profile: apparmor-profile
    + debian/rules, debian/mysql-server-5.1.files: install apparmor profile
    + debian/mysql-server-5.1.dirs: add etc/apparmor.d/fore-complain
    + debian/mysql-server-5.1.postrm: remove symlink in force-complain/ on purge.
    + debian/mysql-server-5.1.README.Debian: add apparmor documentation.
    + debian/additions/my.cnf: Add warning about apparmor. (LP: #201799)
    + debian/mysql-server-5.1.postinst: reload apparmor profiles
  * Convert the package from sysvinit to upstart:
    + debian/mysql-server-5.1.mysql.upstart: Add upstart script.
    + debian/mysql-server-5.1.mysql.init: Dropped, unused now with upstart.
    + debian/additions/mysqld_safe_syslog.cnf: Dropped, unused now with upstart.
    + debian/additons/my.cnf: Remove pid declaration and setup error logging to /var/log/mysql since
      we're not piping anything around logger anymore.
    + debian/rules, debian/mysql-server-5.1.logcheck.ignore.{paranoid,worstation},
      debian/mysql-server-5.1.logcheck.ignore.server: : Remove references to mysqld_safe
    + debian/patches/38_scripts_mysqld_safe.sh_signals.dpatch: Dropped
  * Added -fno-strict-aliasing to CFLAGS to get around mysql testsuite build failures.
  * Add Apport hook (LP: #354188):
    + debian/mysql-server-5.1.py: apport package hook
    + debian/rules: Make it installable
  * debian/mysql-server-5.1.mysql-server.logrotate: Check to see if mysql is running before
    running logrotate. (LP: #513135)
  * Make the testsuite installable. (LP: #530752)
    + debian/mysql-server-5.1.files, debian/rules: install apport package hook
  * debian/mysql-server-5.1.preinst: Set mysql user's home directory
    to /nonexistent to protect against having the /var/lib/mysql
    user-writeable. If an attacker can trick mysqld into creating
    dot files in the home directory, he could do .rhost-like attacks
    on the system. (LP: #293258)
  * debian/control: mysql-client-5.1 should depend on mysql-core-client-5.1.
    (LP: #590952)
  * debian/mysql-server.5.1.postinst: Specify the mysql user when installing 
    the mysql databases. (LP: #591875)
  * Installing mysql_config_pic in /usr/bin so users of libmysqld-pic
    can extract the appropriate compile flags. (LP: #605021) 

Show diffs side-by-side

added added

removed removed

Lines of Context:
80
80
/** Identifies generated InnoDB foreign key names */
81
81
static char     dict_ibfk[] = "_ibfk_";
82
82
 
83
 
/** array of mutexes protecting dict_index_t::stat_n_diff_key_vals[] */
84
 
#define DICT_INDEX_STAT_MUTEX_SIZE      32
85
 
static mutex_t  dict_index_stat_mutex[DICT_INDEX_STAT_MUTEX_SIZE];
 
83
/** array of rw locks protecting
 
84
dict_table_t::stat_initialized
 
85
dict_table_t::stat_n_rows (*)
 
86
dict_table_t::stat_clustered_index_size
 
87
dict_table_t::stat_sum_of_other_index_sizes
 
88
dict_table_t::stat_modified_counter (*)
 
89
dict_table_t::indexes*::stat_n_diff_key_vals[]
 
90
dict_table_t::indexes*::stat_index_size
 
91
dict_table_t::indexes*::stat_n_leaf_pages
 
92
(*) those are not always protected for performance reasons */
 
93
#define DICT_TABLE_STATS_LATCHES_SIZE   64
 
94
static rw_lock_t        dict_table_stats_latches[DICT_TABLE_STATS_LATCHES_SIZE];
86
95
 
87
96
/*******************************************************************//**
88
97
Tries to find column names for the index and sets the col field of the
243
252
        mutex_exit(&(dict_sys->mutex));
244
253
}
245
254
 
246
 
/** Get the mutex that protects index->stat_n_diff_key_vals[] */
247
 
#define GET_INDEX_STAT_MUTEX(index) \
248
 
        (&dict_index_stat_mutex[ut_fold_dulint(index->id) \
249
 
                                % DICT_INDEX_STAT_MUTEX_SIZE])
 
255
/** Get the latch that protects the stats of a given table */
 
256
#define GET_TABLE_STATS_LATCH(table) \
 
257
        (&dict_table_stats_latches[ut_fold_dulint(table->id) \
 
258
                                   % DICT_TABLE_STATS_LATCHES_SIZE])
250
259
 
251
260
/**********************************************************************//**
252
 
Lock the appropriate mutex to protect index->stat_n_diff_key_vals[].
253
 
index->id is used to pick the right mutex and it should not change
254
 
before dict_index_stat_mutex_exit() is called on this index. */
 
261
Lock the appropriate latch to protect a given table's statistics.
 
262
table->id is used to pick the corresponding latch from a global array of
 
263
latches. */
255
264
UNIV_INTERN
256
265
void
257
 
dict_index_stat_mutex_enter(
258
 
/*========================*/
259
 
        const dict_index_t*     index)  /*!< in: index */
 
266
dict_table_stats_lock(
 
267
/*==================*/
 
268
        const dict_table_t*     table,          /*!< in: table */
 
269
        ulint                   latch_mode)     /*!< in: RW_S_LATCH or
 
270
                                                RW_X_LATCH */
260
271
{
261
 
        ut_ad(index != NULL);
262
 
        ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
263
 
        ut_ad(index->cached);
264
 
        ut_ad(!index->to_be_dropped);
 
272
        ut_ad(table != NULL);
 
273
        ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
265
274
 
266
 
        mutex_enter(GET_INDEX_STAT_MUTEX(index));
 
275
        switch (latch_mode) {
 
276
        case RW_S_LATCH:
 
277
                rw_lock_s_lock(GET_TABLE_STATS_LATCH(table));
 
278
                break;
 
279
        case RW_X_LATCH:
 
280
                rw_lock_x_lock(GET_TABLE_STATS_LATCH(table));
 
281
                break;
 
282
        case RW_NO_LATCH:
 
283
                /* fall through */
 
284
        default:
 
285
                ut_error;
 
286
        }
267
287
}
268
288
 
269
289
/**********************************************************************//**
270
 
Unlock the appropriate mutex that protects index->stat_n_diff_key_vals[]. */
 
290
Unlock the latch that has been locked by dict_table_stats_lock() */
271
291
UNIV_INTERN
272
292
void
273
 
dict_index_stat_mutex_exit(
274
 
/*=======================*/
275
 
        const dict_index_t*     index)  /*!< in: index */
 
293
dict_table_stats_unlock(
 
294
/*====================*/
 
295
        const dict_table_t*     table,          /*!< in: table */
 
296
        ulint                   latch_mode)     /*!< in: RW_S_LATCH or
 
297
                                                RW_X_LATCH */
276
298
{
277
 
        ut_ad(index != NULL);
278
 
        ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
279
 
        ut_ad(index->cached);
280
 
        ut_ad(!index->to_be_dropped);
 
299
        ut_ad(table != NULL);
 
300
        ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
281
301
 
282
 
        mutex_exit(GET_INDEX_STAT_MUTEX(index));
 
302
        switch (latch_mode) {
 
303
        case RW_S_LATCH:
 
304
                rw_lock_s_unlock(GET_TABLE_STATS_LATCH(table));
 
305
                break;
 
306
        case RW_X_LATCH:
 
307
                rw_lock_x_unlock(GET_TABLE_STATS_LATCH(table));
 
308
                break;
 
309
        case RW_NO_LATCH:
 
310
                /* fall through */
 
311
        default:
 
312
                ut_error;
 
313
        }
283
314
}
284
315
 
285
316
/********************************************************************//**
568
599
{
569
600
        dict_table_t*   table;
570
601
 
571
 
        if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0
572
 
            || trx->dict_operation_lock_mode == RW_X_LATCH) {
 
602
        if (trx->dict_operation_lock_mode == RW_X_LATCH) {
573
603
 
574
604
                /* Note: An X latch implies that the transaction
575
605
                already owns the dictionary mutex. */
669
699
 
670
700
        mutex_create(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
671
701
 
672
 
        for (i = 0; i < DICT_INDEX_STAT_MUTEX_SIZE; i++) {
673
 
                mutex_create(&dict_index_stat_mutex[i], SYNC_INDEX_TREE);
 
702
        for (i = 0; i < DICT_TABLE_STATS_LATCHES_SIZE; i++) {
 
703
                rw_lock_create(&dict_table_stats_latches[i], SYNC_INDEX_TREE);
674
704
        }
675
705
}
676
706
 
701
731
        mutex_exit(&(dict_sys->mutex));
702
732
 
703
733
        if (table != NULL) {
704
 
                if (!table->stat_initialized) {
705
 
                        /* If table->ibd_file_missing == TRUE, this will
706
 
                        print an error message and return without doing
707
 
                        anything. */
708
 
                        dict_update_statistics(table);
709
 
                }
 
734
                /* If table->ibd_file_missing == TRUE, this will
 
735
                print an error message and return without doing
 
736
                anything. */
 
737
                dict_update_statistics(table, TRUE /* only update stats
 
738
                                       if they have not been initialized */);
710
739
        }
711
740
 
712
741
        return(table);
4184
4213
are used in query optimization. */
4185
4214
UNIV_INTERN
4186
4215
void
4187
 
dict_update_statistics_low(
4188
 
/*=======================*/
 
4216
dict_update_statistics(
 
4217
/*===================*/
4189
4218
        dict_table_t*   table,          /*!< in/out: table */
4190
 
        ibool           has_dict_mutex __attribute__((unused)))
4191
 
                                        /*!< in: TRUE if the caller has the
4192
 
                                        dictionary mutex */
 
4219
        ibool           only_calc_if_missing_stats)/*!< in: only
 
4220
                                        update/recalc the stats if they have
 
4221
                                        not been initialized yet, otherwise
 
4222
                                        do nothing */
4193
4223
{
4194
4224
        dict_index_t*   index;
4195
 
        ulint           size;
4196
4225
        ulint           sum_of_index_sizes      = 0;
4197
4226
 
4198
4227
        if (table->ibd_file_missing) {
4207
4236
                return;
4208
4237
        }
4209
4238
 
4210
 
        /* If we have set a high innodb_force_recovery level, do not calculate
4211
 
        statistics, as a badly corrupted index can cause a crash in it. */
4212
 
 
4213
 
        if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
4214
 
 
4215
 
                return;
4216
 
        }
4217
 
 
4218
4239
        /* Find out the sizes of the indexes and how many different values
4219
4240
        for the key they approximately have */
4220
4241
 
4226
4247
                return;
4227
4248
        }
4228
4249
 
4229
 
        while (index) {
4230
 
                size = btr_get_size(index, BTR_TOTAL_SIZE);
4231
 
 
4232
 
                index->stat_index_size = size;
4233
 
 
4234
 
                sum_of_index_sizes += size;
4235
 
 
4236
 
                size = btr_get_size(index, BTR_N_LEAF_PAGES);
4237
 
 
4238
 
                if (size == 0) {
4239
 
                        /* The root node of the tree is a leaf */
4240
 
                        size = 1;
 
4250
        dict_table_stats_lock(table, RW_X_LATCH);
 
4251
 
 
4252
        if (only_calc_if_missing_stats && table->stat_initialized) {
 
4253
                dict_table_stats_unlock(table, RW_X_LATCH);
 
4254
                return;
 
4255
        }
 
4256
 
 
4257
        do {
 
4258
                if (UNIV_LIKELY
 
4259
                    (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE
 
4260
                     || (srv_force_recovery < SRV_FORCE_NO_LOG_REDO
 
4261
                         && dict_index_is_clust(index)))) {
 
4262
                        ulint   size;
 
4263
                        size = btr_get_size(index, BTR_TOTAL_SIZE);
 
4264
 
 
4265
                        index->stat_index_size = size;
 
4266
 
 
4267
                        sum_of_index_sizes += size;
 
4268
 
 
4269
                        size = btr_get_size(index, BTR_N_LEAF_PAGES);
 
4270
 
 
4271
                        if (size == 0) {
 
4272
                                /* The root node of the tree is a leaf */
 
4273
                                size = 1;
 
4274
                        }
 
4275
 
 
4276
                        index->stat_n_leaf_pages = size;
 
4277
 
 
4278
                        btr_estimate_number_of_different_key_vals(index);
 
4279
                } else {
 
4280
                        /* If we have set a high innodb_force_recovery
 
4281
                        level, do not calculate statistics, as a badly
 
4282
                        corrupted index can cause a crash in it.
 
4283
                        Initialize some bogus index cardinality
 
4284
                        statistics, so that the data can be queried in
 
4285
                        various means, also via secondary indexes. */
 
4286
                        ulint   i;
 
4287
 
 
4288
                        sum_of_index_sizes++;
 
4289
                        index->stat_index_size = index->stat_n_leaf_pages = 1;
 
4290
 
 
4291
                        for (i = dict_index_get_n_unique(index); i; ) {
 
4292
                                index->stat_n_diff_key_vals[i--] = 1;
 
4293
                        }
4241
4294
                }
4242
4295
 
4243
 
                index->stat_n_leaf_pages = size;
4244
 
 
4245
 
                btr_estimate_number_of_different_key_vals(index);
4246
 
 
4247
4296
                index = dict_table_get_next_index(index);
4248
 
        }
 
4297
        } while (index);
4249
4298
 
4250
4299
        index = dict_table_get_first_index(table);
4251
4300
 
4252
 
        dict_index_stat_mutex_enter(index);
4253
 
 
4254
4301
        table->stat_n_rows = index->stat_n_diff_key_vals[
4255
4302
                dict_index_get_n_unique(index)];
4256
4303
 
4257
 
        dict_index_stat_mutex_exit(index);
4258
 
 
4259
4304
        table->stat_clustered_index_size = index->stat_index_size;
4260
4305
 
4261
4306
        table->stat_sum_of_other_index_sizes = sum_of_index_sizes
4264
4309
        table->stat_initialized = TRUE;
4265
4310
 
4266
4311
        table->stat_modified_counter = 0;
4267
 
}
4268
4312
 
4269
 
/*********************************************************************//**
4270
 
Calculates new estimates for table and index statistics. The statistics
4271
 
are used in query optimization. */
4272
 
UNIV_INTERN
4273
 
void
4274
 
dict_update_statistics(
4275
 
/*===================*/
4276
 
        dict_table_t*   table)  /*!< in/out: table */
4277
 
{
4278
 
        dict_update_statistics_low(table, FALSE);
 
4313
        dict_table_stats_unlock(table, RW_X_LATCH);
4279
4314
}
4280
4315
 
4281
4316
/**********************************************************************//**
4355
4390
 
4356
4391
        ut_ad(mutex_own(&(dict_sys->mutex)));
4357
4392
 
4358
 
        dict_update_statistics_low(table, TRUE);
 
4393
        dict_update_statistics(table, FALSE /* update even if initialized */);
 
4394
 
 
4395
        dict_table_stats_lock(table, RW_S_LATCH);
4359
4396
 
4360
4397
        fprintf(stderr,
4361
4398
                "--------------------------------------\n"
4384
4421
                index = UT_LIST_GET_NEXT(indexes, index);
4385
4422
        }
4386
4423
 
 
4424
        dict_table_stats_unlock(table, RW_S_LATCH);
 
4425
 
4387
4426
        foreign = UT_LIST_GET_FIRST(table->foreign_list);
4388
4427
 
4389
4428
        while (foreign != NULL) {
4429
4468
{
4430
4469
        ib_int64_t      n_vals;
4431
4470
        ulint           i;
4432
 
        const char*     type_string;
4433
4471
 
4434
4472
        ut_ad(mutex_own(&(dict_sys->mutex)));
4435
4473
 
4436
 
        dict_index_stat_mutex_enter(index);
4437
 
 
4438
4474
        if (index->n_user_defined_cols > 0) {
4439
4475
                n_vals = index->stat_n_diff_key_vals[
4440
4476
                        index->n_user_defined_cols];
4442
4478
                n_vals = index->stat_n_diff_key_vals[1];
4443
4479
        }
4444
4480
 
4445
 
        dict_index_stat_mutex_exit(index);
4446
 
 
4447
 
        if (dict_index_is_clust(index)) {
4448
 
                type_string = "clustered index";
4449
 
        } else if (dict_index_is_unique(index)) {
4450
 
                type_string = "unique index";
4451
 
        } else {
4452
 
                type_string = "secondary index";
4453
 
        }
4454
 
 
4455
4481
        fprintf(stderr,
4456
4482
                "  INDEX: name %s, id %lu %lu, fields %lu/%lu,"
4457
4483
                " uniq %lu, type %lu\n"
4795
4821
dict_table_replace_index_in_foreign_list(
4796
4822
/*=====================================*/
4797
4823
        dict_table_t*   table,  /*!< in/out: table */
4798
 
        dict_index_t*   index)  /*!< in: index to be replaced */
 
4824
        dict_index_t*   index,  /*!< in: index to be replaced */
 
4825
        const trx_t*    trx)    /*!< in: transaction handle */
4799
4826
{
4800
4827
        dict_foreign_t* foreign;
4801
4828
 
4806
4833
                if (foreign->foreign_index == index) {
4807
4834
                        dict_index_t*   new_index
4808
4835
                                = dict_foreign_find_equiv_index(foreign);
4809
 
                        ut_a(new_index);
 
4836
 
 
4837
                        /* There must exist an alternative index if
 
4838
                        check_foreigns (FOREIGN_KEY_CHECKS) is on, 
 
4839
                        since ha_innobase::prepare_drop_index had done
 
4840
                        the check before we reach here. */
 
4841
 
 
4842
                        ut_a(new_index || !trx->check_foreigns);
4810
4843
 
4811
4844
                        foreign->foreign_index = new_index;
4812
4845
                }
4940
4973
        mem_free(dict_sys);
4941
4974
        dict_sys = NULL;
4942
4975
 
4943
 
        for (i = 0; i < DICT_INDEX_STAT_MUTEX_SIZE; i++) {
4944
 
                mutex_free(&dict_index_stat_mutex[i]);
 
4976
        for (i = 0; i < DICT_TABLE_STATS_LATCHES_SIZE; i++) {
 
4977
                rw_lock_free(&dict_table_stats_latches[i]);
4945
4978
        }
4946
4979
}
4947
4980
#endif /* !UNIV_HOTBACKUP */