~clint-fewbar/ubuntu/natty/mysql-5.1/merge-5.1.49-2

« back to all changes in this revision

Viewing changes to storage/innodb_plugin/lock/lock0lock.c

  • Committer: Bazaar Package Importer
  • Author(s): Chuck Short
  • Date: 2010-08-04 13:18:27 UTC
  • mfrom: (1.2.2 upstream) (2.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20100804131827-4tjg88vr9dd49s3k
Tags: 5.1.49-1ubuntu1
* 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) 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1733
1733
Enqueues a waiting request for a lock which cannot be granted immediately.
1734
1734
Checks for deadlocks.
1735
1735
@return DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED, or
1736
 
DB_SUCCESS; DB_SUCCESS means that there was a deadlock, but another
1737
 
transaction was chosen as a victim, and we got the lock immediately:
1738
 
no need to wait then */
 
1736
DB_SUCCESS_LOCKED_REC; DB_SUCCESS_LOCKED_REC means that
 
1737
there was a deadlock, but another transaction was chosen as a victim,
 
1738
and we got the lock immediately: no need to wait then */
1739
1739
static
1740
 
ulint
 
1740
enum db_err
1741
1741
lock_rec_enqueue_waiting(
1742
1742
/*=====================*/
1743
1743
        ulint                   type_mode,/*!< in: lock mode this
1809
1809
 
1810
1810
        if (trx->wait_lock == NULL) {
1811
1811
 
1812
 
                return(DB_SUCCESS);
 
1812
                return(DB_SUCCESS_LOCKED_REC);
1813
1813
        }
1814
1814
 
1815
1815
        trx->que_state = TRX_QUE_LOCK_WAIT;
1925
1925
        return(lock_rec_create(type_mode, block, heap_no, index, trx));
1926
1926
}
1927
1927
 
 
1928
/** Record locking request status */
 
1929
enum lock_rec_req_status {
 
1930
        /** Failed to acquire a lock */
 
1931
        LOCK_REC_FAIL,
 
1932
        /** Succeeded in acquiring a lock (implicit or already acquired) */
 
1933
        LOCK_REC_SUCCESS,
 
1934
        /** Explicitly created a new lock */
 
1935
        LOCK_REC_SUCCESS_CREATED
 
1936
};
 
1937
 
1928
1938
/*********************************************************************//**
1929
1939
This is a fast routine for locking a record in the most common cases:
1930
1940
there are no explicit locks on the page, or there is just one lock, owned
1932
1942
which does NOT look at implicit locks! Checks lock compatibility within
1933
1943
explicit locks. This function sets a normal next-key lock, or in the case of
1934
1944
a page supremum record, a gap type lock.
1935
 
@return TRUE if locking succeeded */
 
1945
@return whether the locking succeeded */
1936
1946
UNIV_INLINE
1937
 
ibool
 
1947
enum lock_rec_req_status
1938
1948
lock_rec_lock_fast(
1939
1949
/*===============*/
1940
1950
        ibool                   impl,   /*!< in: if TRUE, no lock is set
1973
1983
                        lock_rec_create(mode, block, heap_no, index, trx);
1974
1984
                }
1975
1985
 
1976
 
                return(TRUE);
 
1986
                return(LOCK_REC_SUCCESS_CREATED);
1977
1987
        }
1978
1988
 
1979
1989
        if (lock_rec_get_next_on_page(lock)) {
1980
1990
 
1981
 
                return(FALSE);
 
1991
                return(LOCK_REC_FAIL);
1982
1992
        }
1983
1993
 
1984
1994
        if (lock->trx != trx
1985
1995
            || lock->type_mode != (mode | LOCK_REC)
1986
1996
            || lock_rec_get_n_bits(lock) <= heap_no) {
1987
1997
 
1988
 
                return(FALSE);
 
1998
                return(LOCK_REC_FAIL);
1989
1999
        }
1990
2000
 
1991
2001
        if (!impl) {
1994
2004
 
1995
2005
                if (!lock_rec_get_nth_bit(lock, heap_no)) {
1996
2006
                        lock_rec_set_nth_bit(lock, heap_no);
 
2007
                        return(LOCK_REC_SUCCESS_CREATED);
1997
2008
                }
1998
2009
        }
1999
2010
 
2000
 
        return(TRUE);
 
2011
        return(LOCK_REC_SUCCESS);
2001
2012
}
2002
2013
 
2003
2014
/*********************************************************************//**
2005
2016
low-level function which does NOT look at implicit locks! Checks lock
2006
2017
compatibility within explicit locks. This function sets a normal next-key
2007
2018
lock, or in the case of a page supremum record, a gap type lock.
2008
 
@return DB_SUCCESS, DB_LOCK_WAIT, or error code */
 
2019
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
 
2020
or DB_QUE_THR_SUSPENDED */
2009
2021
static
2010
 
ulint
 
2022
enum db_err
2011
2023
lock_rec_lock_slow(
2012
2024
/*===============*/
2013
2025
        ibool                   impl,   /*!< in: if TRUE, no lock is set
2024
2036
        que_thr_t*              thr)    /*!< in: query thread */
2025
2037
{
2026
2038
        trx_t*  trx;
2027
 
        ulint   err;
2028
2039
 
2029
2040
        ut_ad(mutex_own(&kernel_mutex));
2030
2041
        ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
2043
2054
                /* The trx already has a strong enough lock on rec: do
2044
2055
                nothing */
2045
2056
 
2046
 
                err = DB_SUCCESS;
2047
2057
        } else if (lock_rec_other_has_conflicting(mode, block, heap_no, trx)) {
2048
2058
 
2049
2059
                /* If another transaction has a non-gap conflicting request in
2050
2060
                the queue, as this transaction does not have a lock strong
2051
2061
                enough already granted on the record, we have to wait. */
2052
2062
 
2053
 
                err = lock_rec_enqueue_waiting(mode, block, heap_no,
2054
 
                                               index, thr);
2055
 
        } else {
2056
 
                if (!impl) {
2057
 
                        /* Set the requested lock on the record */
2058
 
 
2059
 
                        lock_rec_add_to_queue(LOCK_REC | mode, block,
2060
 
                                              heap_no, index, trx);
2061
 
                }
2062
 
 
2063
 
                err = DB_SUCCESS;
 
2063
                return(lock_rec_enqueue_waiting(mode, block, heap_no,
 
2064
                                                index, thr));
 
2065
        } else if (!impl) {
 
2066
                /* Set the requested lock on the record */
 
2067
 
 
2068
                lock_rec_add_to_queue(LOCK_REC | mode, block,
 
2069
                                      heap_no, index, trx);
 
2070
                return(DB_SUCCESS_LOCKED_REC);
2064
2071
        }
2065
2072
 
2066
 
        return(err);
 
2073
        return(DB_SUCCESS);
2067
2074
}
2068
2075
 
2069
2076
/*********************************************************************//**
2072
2079
which does NOT look at implicit locks! Checks lock compatibility within
2073
2080
explicit locks. This function sets a normal next-key lock, or in the case
2074
2081
of a page supremum record, a gap type lock.
2075
 
@return DB_SUCCESS, DB_LOCK_WAIT, or error code */
 
2082
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
 
2083
or DB_QUE_THR_SUSPENDED */
2076
2084
static
2077
 
ulint
 
2085
enum db_err
2078
2086
lock_rec_lock(
2079
2087
/*==========*/
2080
2088
        ibool                   impl,   /*!< in: if TRUE, no lock is set
2090
2098
        dict_index_t*           index,  /*!< in: index of record */
2091
2099
        que_thr_t*              thr)    /*!< in: query thread */
2092
2100
{
2093
 
        ulint   err;
2094
 
 
2095
2101
        ut_ad(mutex_own(&kernel_mutex));
2096
2102
        ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
2097
2103
              || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
2103
2109
              || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP
2104
2110
              || mode - (LOCK_MODE_MASK & mode) == 0);
2105
2111
 
2106
 
        if (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) {
2107
 
 
2108
 
                /* We try a simplified and faster subroutine for the most
2109
 
                common cases */
2110
 
 
2111
 
                err = DB_SUCCESS;
2112
 
        } else {
2113
 
                err = lock_rec_lock_slow(impl, mode, block,
2114
 
                                         heap_no, index, thr);
 
2112
        /* We try a simplified and faster subroutine for the most
 
2113
        common cases */
 
2114
        switch (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) {
 
2115
        case LOCK_REC_SUCCESS:
 
2116
                return(DB_SUCCESS);
 
2117
        case LOCK_REC_SUCCESS_CREATED:
 
2118
                return(DB_SUCCESS_LOCKED_REC);
 
2119
        case LOCK_REC_FAIL:
 
2120
                return(lock_rec_lock_slow(impl, mode, block,
 
2121
                                          heap_no, index, thr));
2115
2122
        }
2116
2123
 
2117
 
        return(err);
 
2124
        ut_error;
 
2125
        return(DB_ERROR);
2118
2126
}
2119
2127
 
2120
2128
/*********************************************************************//**
3935
3943
        const rec_t*            rec,    /*!< in: record */
3936
3944
        enum lock_mode          lock_mode)/*!< in: LOCK_S or LOCK_X */
3937
3945
{
 
3946
        lock_t* first_lock;
3938
3947
        lock_t* lock;
3939
 
        lock_t* release_lock    = NULL;
3940
3948
        ulint   heap_no;
3941
3949
 
3942
3950
        ut_ad(trx && rec);
3946
3954
 
3947
3955
        mutex_enter(&kernel_mutex);
3948
3956
 
3949
 
        lock = lock_rec_get_first(block, heap_no);
 
3957
        first_lock = lock_rec_get_first(block, heap_no);
3950
3958
 
3951
3959
        /* Find the last lock with the same lock_mode and transaction
3952
3960
        from the record. */
3953
3961
 
3954
 
        while (lock != NULL) {
 
3962
        for (lock = first_lock; lock != NULL;
 
3963
             lock = lock_rec_get_next(heap_no, lock)) {
3955
3964
                if (lock->trx == trx && lock_get_mode(lock) == lock_mode) {
3956
 
                        release_lock = lock;
3957
3965
                        ut_a(!lock_get_wait(lock));
 
3966
                        lock_rec_reset_nth_bit(lock, heap_no);
 
3967
                        goto released;
3958
3968
                }
3959
 
 
3960
 
                lock = lock_rec_get_next(heap_no, lock);
3961
 
        }
3962
 
 
3963
 
        /* If a record lock is found, release the record lock */
3964
 
 
3965
 
        if (UNIV_LIKELY(release_lock != NULL)) {
3966
 
                lock_rec_reset_nth_bit(release_lock, heap_no);
3967
 
        } else {
3968
 
                mutex_exit(&kernel_mutex);
3969
 
                ut_print_timestamp(stderr);
3970
 
                fprintf(stderr,
3971
 
                        "  InnoDB: Error: unlock row could not"
3972
 
                        " find a %lu mode lock on the record\n",
3973
 
                        (ulong) lock_mode);
3974
 
 
3975
 
                return;
3976
 
        }
3977
 
 
 
3969
        }
 
3970
 
 
3971
        mutex_exit(&kernel_mutex);
 
3972
        ut_print_timestamp(stderr);
 
3973
        fprintf(stderr,
 
3974
                "  InnoDB: Error: unlock row could not"
 
3975
                " find a %lu mode lock on the record\n",
 
3976
                (ulong) lock_mode);
 
3977
 
 
3978
        return;
 
3979
 
 
3980
released:
3978
3981
        /* Check if we can now grant waiting lock requests */
3979
3982
 
3980
 
        lock = lock_rec_get_first(block, heap_no);
3981
 
 
3982
 
        while (lock != NULL) {
 
3983
        for (lock = first_lock; lock != NULL;
 
3984
             lock = lock_rec_get_next(heap_no, lock)) {
3983
3985
                if (lock_get_wait(lock)
3984
3986
                    && !lock_rec_has_to_wait_in_queue(lock)) {
3985
3987
 
3986
3988
                        /* Grant the lock */
3987
3989
                        lock_grant(lock);
3988
3990
                }
3989
 
 
3990
 
                lock = lock_rec_get_next(heap_no, lock);
3991
3991
        }
3992
3992
 
3993
3993
        mutex_exit(&kernel_mutex);
5080
5080
 
5081
5081
        lock_mutex_exit_kernel();
5082
5082
 
5083
 
        if ((err == DB_SUCCESS) && !dict_index_is_clust(index)) {
 
5083
        switch (err) {
 
5084
        case DB_SUCCESS_LOCKED_REC:
 
5085
                err = DB_SUCCESS;
 
5086
                /* fall through */
 
5087
        case DB_SUCCESS:
 
5088
                if (dict_index_is_clust(index)) {
 
5089
                        break;
 
5090
                }
5084
5091
                /* Update the page max trx id field */
5085
5092
                page_update_max_trx_id(block,
5086
5093
                                       buf_block_get_page_zip(block),
5203
5210
 
5204
5211
        ut_ad(lock_rec_queue_validate(block, rec, index, offsets));
5205
5212
 
 
5213
        if (UNIV_UNLIKELY(err == DB_SUCCESS_LOCKED_REC)) {
 
5214
                err = DB_SUCCESS;
 
5215
        }
 
5216
 
5206
5217
        return(err);
5207
5218
}
5208
5219
 
5269
5280
        }
5270
5281
#endif /* UNIV_DEBUG */
5271
5282
 
5272
 
        if (err == DB_SUCCESS) {
 
5283
        if (err == DB_SUCCESS || err == DB_SUCCESS_LOCKED_REC) {
5273
5284
                /* Update the page max trx id field */
 
5285
                /* It might not be necessary to do this if
 
5286
                err == DB_SUCCESS (no new lock created),
 
5287
                but it should not cost too much performance. */
5274
5288
                page_update_max_trx_id(block,
5275
5289
                                       buf_block_get_page_zip(block),
5276
5290
                                       thr_get_trx(thr)->id, mtr);
 
5291
                err = DB_SUCCESS;
5277
5292
        }
5278
5293
 
5279
5294
        return(err);
5280
5295
}
5281
5296
 
5282
5297
/*********************************************************************//**
5283
 
Like the counterpart for a clustered index below, but now we read a
 
5298
Like lock_clust_rec_read_check_and_lock(), but reads a
5284
5299
secondary index record.
5285
 
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
 
5300
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
 
5301
or DB_QUE_THR_SUSPENDED */
5286
5302
UNIV_INTERN
5287
 
ulint
 
5303
enum db_err
5288
5304
lock_sec_rec_read_check_and_lock(
5289
5305
/*=============================*/
5290
5306
        ulint                   flags,  /*!< in: if BTR_NO_LOCKING_FLAG
5305
5321
                                        LOCK_REC_NOT_GAP */
5306
5322
        que_thr_t*              thr)    /*!< in: query thread */
5307
5323
{
5308
 
        ulint   err;
5309
 
        ulint   heap_no;
 
5324
        enum db_err     err;
 
5325
        ulint           heap_no;
5310
5326
 
5311
5327
        ut_ad(!dict_index_is_clust(index));
5312
5328
        ut_ad(block->frame == page_align(rec));
5357
5373
puts the transaction and the query thread to the lock wait state and inserts a
5358
5374
waiting request for a record lock to the lock queue. Sets the requested mode
5359
5375
lock on the record.
5360
 
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
 
5376
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
 
5377
or DB_QUE_THR_SUSPENDED */
5361
5378
UNIV_INTERN
5362
 
ulint
 
5379
enum db_err
5363
5380
lock_clust_rec_read_check_and_lock(
5364
5381
/*===============================*/
5365
5382
        ulint                   flags,  /*!< in: if BTR_NO_LOCKING_FLAG
5380
5397
                                        LOCK_REC_NOT_GAP */
5381
5398
        que_thr_t*              thr)    /*!< in: query thread */
5382
5399
{
5383
 
        ulint   err;
5384
 
        ulint   heap_no;
 
5400
        enum db_err     err;
 
5401
        ulint           heap_no;
5385
5402
 
5386
5403
        ut_ad(dict_index_is_clust(index));
5387
5404
        ut_ad(block->frame == page_align(rec));
5452
5469
        mem_heap_t*     tmp_heap        = NULL;
5453
5470
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
5454
5471
        ulint*          offsets         = offsets_;
5455
 
        ulint           ret;
 
5472
        ulint           err;
5456
5473
        rec_offs_init(offsets_);
5457
5474
 
5458
5475
        offsets = rec_get_offsets(rec, index, offsets,
5459
5476
                                  ULINT_UNDEFINED, &tmp_heap);
5460
 
        ret = lock_clust_rec_read_check_and_lock(flags, block, rec, index,
 
5477
        err = lock_clust_rec_read_check_and_lock(flags, block, rec, index,
5461
5478
                                                 offsets, mode, gap_mode, thr);
5462
5479
        if (tmp_heap) {
5463
5480
                mem_heap_free(tmp_heap);
5464
5481
        }
5465
 
        return(ret);
 
5482
 
 
5483
        if (UNIV_UNLIKELY(err == DB_SUCCESS_LOCKED_REC)) {
 
5484
                err = DB_SUCCESS;
 
5485
        }
 
5486
 
 
5487
        return(err);
5466
5488
}
5467
5489
 
5468
5490
/*******************************************************************//**