List:Commits« Previous MessageNext Message »
From:paul.dubois Date:July 14 2010 3:35pm
Subject:svn commit - mysqldoc@docsrva: r21728 - in trunk: . refman-4.1 refman-5.0 refman-5.1 refman-5.5 refman-6.0
View as plain text  
Author: paul
Date: 2010-07-14 17:35:58 +0200 (Wed, 14 Jul 2010)
New Revision: 21728

Log:
 r61174@frost:  paul | 2010-07-14 10:32:19 -0500
 Some optimization chapter reorganization


Modified:
   trunk/refman-4.1/data-types.xml
   trunk/refman-4.1/optimization.xml
   trunk/refman-4.1/renamed-nodes.txt
   trunk/refman-4.1/sql-syntax-data-definition.xml
   trunk/refman-5.0/data-types.xml
   trunk/refman-5.0/optimization.xml
   trunk/refman-5.0/renamed-nodes.txt
   trunk/refman-5.0/sql-syntax-data-definition.xml
   trunk/refman-5.1/data-types.xml
   trunk/refman-5.1/optimization.xml
   trunk/refman-5.1/renamed-nodes.txt
   trunk/refman-5.1/sql-syntax-data-definition.xml
   trunk/refman-5.5/data-types.xml
   trunk/refman-5.5/optimization.xml
   trunk/refman-5.5/renamed-nodes.txt
   trunk/refman-5.5/sql-syntax-data-definition.xml
   trunk/refman-6.0/data-types.xml
   trunk/refman-6.0/optimization.xml
   trunk/refman-6.0/sql-syntax-data-definition.xml

Property changes on: trunk
___________________________________________________________________
Name: svk:merge
   - 07c7e7b4-24e3-4b51-89d0-6dc09fec6bec:/mysqldoc-local/mysqldoc/trunk:35498
07c7e7b4-24e3-4b51-89d0-6dc09fec6bec:/mysqldoc-local/trunk:40851
4767c598-dc10-0410-bea0-d01b485662eb:/mysqldoc-local/mysqldoc/trunk:43968
4767c598-dc10-0410-bea0-d01b485662eb:/mysqldoc-local/trunk:44480
7d8d2c4e-af1d-0410-ab9f-b038ce55645b:/mysqldoc-local/mysqldoc:61170
b5ec3a16-e900-0410-9ad2-d183a3acac99:/mysqldoc-local/mysqldoc/trunk:14218
bf112a9c-6c03-0410-a055-ad865cd57414:/mysqldoc-local/mysqldoc/trunk:39036
bf112a9c-6c03-0410-a055-ad865cd57414:/mysqldoc-local/trunk:39546
   + 07c7e7b4-24e3-4b51-89d0-6dc09fec6bec:/mysqldoc-local/mysqldoc/trunk:35498
07c7e7b4-24e3-4b51-89d0-6dc09fec6bec:/mysqldoc-local/trunk:40851
4767c598-dc10-0410-bea0-d01b485662eb:/mysqldoc-local/mysqldoc/trunk:43968
4767c598-dc10-0410-bea0-d01b485662eb:/mysqldoc-local/trunk:44480
7d8d2c4e-af1d-0410-ab9f-b038ce55645b:/mysqldoc-local/mysqldoc:61174
b5ec3a16-e900-0410-9ad2-d183a3acac99:/mysqldoc-local/mysqldoc/trunk:14218
bf112a9c-6c03-0410-a055-ad865cd57414:/mysqldoc-local/mysqldoc/trunk:39036
bf112a9c-6c03-0410-a055-ad865cd57414:/mysqldoc-local/trunk:39546


Modified: trunk/refman-4.1/data-types.xml
===================================================================
--- trunk/refman-4.1/data-types.xml	2010-07-14 15:11:37 UTC (rev 21727)
+++ trunk/refman-4.1/data-types.xml	2010-07-14 15:35:58 UTC (rev 21728)
Changed blocks: 1, Lines Added: 1, Lines Deleted: 1; 594 bytes

@@ -5115,7 +5115,7 @@
             specify an index prefix length. For
             <literal role="type">CHAR</literal> and
             <literal role="type">VARCHAR</literal>, a prefix length is
-            optional. See <xref linkend="indexes"/>.
+            optional. See <xref linkend="column-indexes"/>.
           </para>
         </listitem>
 


Modified: trunk/refman-4.1/optimization.xml
===================================================================
--- trunk/refman-4.1/optimization.xml	2010-07-14 15:11:37 UTC (rev 21727)
+++ trunk/refman-4.1/optimization.xml	2010-07-14 15:35:58 UTC (rev 21728)
Changed blocks: 3, Lines Added: 1104, Lines Deleted: 1098; 79638 bytes

@@ -5277,1106 +5277,12 @@
 
   </section>
 
-  <section id="locking-issues">
+  <section id="optimization-indexes">
 
-    <title>Locking Issues</title>
+    <title>Optimization and Indexes</title>
 
-    <para>
-      MySQL manages contention for table contents using locking:
-    </para>
+    <section id="column-indexes">
 
-    <itemizedlist>
-
-      <listitem>
-        <para>
-          Internal locking is performed within the MySQL server itself
-          to manage contention for table contents by multiple threads.
-          This type of locking is internal because it is performed
-          entirely by the server and involves no other programs. See
-          <xref linkend="internal-locking"/>.
-        </para>
-      </listitem>
-
-      <listitem>
-        <para>
-          External locking occurs when the server and other programs
-          lock table files to coordinate among themselves which program
-          can access the tables at which time. See
-          <xref linkend="external-locking"/>.
-        </para>
-      </listitem>
-
-    </itemizedlist>
-
-    <section id="internal-locking">
-
-      <title>Internal Locking Methods</title>
-
-      <indexterm>
-        <primary>internal locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>internal</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking methods</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>methods</primary>
-        <secondary>locking</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>row-level locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>page-level locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>table-level locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>row-level</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>page-level</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>table-level</secondary>
-      </indexterm>
-
-      <para>
-        This section discusses internal locking; that is, locking
-        performed within the MySQL server itself to manage contention
-        for table contents by multiple sessions. This type of locking is
-        internal because it is performed entirely by the server and
-        involves no other programs. External locking occurs when the
-        server and other programs lock table files to coordinate among
-        themselves which program can access the tables at which time.
-        See <xref linkend="external-locking"/>.
-      </para>
-
-      <para>
-        MySQL uses table-level locking for <literal>ISAM</literal>,
-        <literal>MyISAM</literal>, <literal>MEMORY</literal>
-        (<literal>HEAP</literal>), and <literal>MERGE</literal> tables,
-        page-level locking for <literal>BDB</literal> tables, and
-        row-level locking for <literal>InnoDB</literal> tables.
-      </para>
-
-      <para>
-        In many cases, you can make an educated guess about which
-        locking type is best for an application, but generally it is
-        difficult to say that a given lock type is better than another.
-        Everything depends on the application and different parts of an
-        application may require different lock types.
-      </para>
-
-      <para>
-        To decide whether you want to use a storage engine with
-        row-level locking, you should look at what your application does
-        and what mix of select and update statements it uses. For
-        example, most Web applications perform many selects, relatively
-        few deletes, updates based mainly on key values, and inserts
-        into a few specific tables. The base MySQL
-        <literal>MyISAM</literal> setup is very well tuned for this.
-      </para>
-
-      <formalpara role="mnmas">
-
-        <title>MySQL Enterprise</title>
-
-        <para>
-          The MySQL Enterprise Monitor provides expert advice on when to
-          use table-level locking and when to use row-level locking. To
-          subscribe, see &base-url-enterprise;advisors.html.
-        </para>
-
-      </formalpara>
-
-      <para>
-        Table locking in MySQL is deadlock-free for storage engines that
-        use table-level locking. Deadlock avoidance is managed by always
-        requesting all needed locks at once at the beginning of a query
-        and always locking the tables in the same order.
-      </para>
-
-      <para>
-        MySQL grants table write locks as follows:
-      </para>
-
-      <orderedlist>
-
-        <listitem>
-          <para>
-            If there are no locks on the table, put a write lock on it.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Otherwise, put the lock request in the write lock queue.
-          </para>
-        </listitem>
-
-      </orderedlist>
-
-      <para>
-        MySQL grants table read locks as follows:
-      </para>
-
-      <orderedlist>
-
-        <listitem>
-          <para>
-            If there are no write locks on the table, put a read lock on
-            it.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Otherwise, put the lock request in the read lock queue.
-          </para>
-        </listitem>
-
-      </orderedlist>
-
-      <para>
-        Table updates are given higher priority than table retrievals.
-        Therefore, when a lock is released, the lock is made available
-        to the requests in the write lock queue and then to the requests
-        in the read lock queue. This ensures that updates to a table are
-        not <quote>starved</quote> even if there is heavy
-        <literal role="stmt">SELECT</literal> activity for the table.
-        However, if you have many updates for a table,
-        <literal role="stmt">SELECT</literal> statements wait until
-        there are no more updates.
-      </para>
-
-      <para>
-        For information on altering the priority of reads and writes,
-        see <xref linkend="table-locking"/>.
-      </para>
-
-      <para>
-        Starting in MySQL 3.23.33, you can analyze the table lock
-        contention on your system by checking the
-        <literal role="statvar">Table_locks_immediate</literal> and
-        <literal role="statvar">Table_locks_waited</literal> status
-        variables, which indicate the number of times that requests for
-        table locks could be granted immediately and the number that had
-        to wait, respectively:
-      </para>
-
-<programlisting>
-mysql&gt; <userinput>SHOW STATUS LIKE 'Table%';</userinput>
-+-----------------------+---------+
-| Variable_name         | Value   |
-+-----------------------+---------+
-| Table_locks_immediate | 1151552 |
-| Table_locks_waited    | 15324   |
-+-----------------------+---------+
-</programlisting>
-
-      <indexterm>
-        <primary>concurrent inserts</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>inserts</primary>
-        <secondary>concurrent</secondary>
-      </indexterm>
-
-      <para>
-        As of MySQL 3.23.7 (3.23.25 for Windows), the
-        <literal>MyISAM</literal> storage engine supports concurrent
-        inserts to reduce contention between readers and writers for a
-        given table: If a <literal>MyISAM</literal> table has no free
-        blocks in the middle of the data file, rows are always inserted
-        at the end of the data file. In this case, you can freely mix
-        concurrent <literal role="stmt">INSERT</literal> and
-        <literal role="stmt">SELECT</literal> statements for a
-        <literal>MyISAM</literal> table without locks. That is, you can
-        insert rows into a <literal>MyISAM</literal> table at the same
-        time other clients are reading from it. (Holes can result from
-        rows having been deleted from or updated in the middle of the
-        table. If there are holes, concurrent inserts are disabled but
-        are enabled again automatically when all holes have been filled
-        with new data.)
-      </para>
-
-      <para>
-        If you acquire a table lock explicitly with
-        <literal role="stmt">LOCK TABLES</literal>, you can request a
-        <literal>READ LOCAL</literal> lock rather than a
-        <literal>READ</literal> lock to enable other sessions to perform
-        concurrent inserts while you have the table locked.
-      </para>
-
-      <para>
-        To perform many <literal role="stmt">INSERT</literal> and
-        <literal role="stmt">SELECT</literal> operations on a table
-        <literal>real_table</literal> when concurrent inserts are not
-        possible, you can insert rows into a temporary table
-        <literal>temp_table</literal> and update the real table with the
-        rows from the temporary table periodically. This can be done
-        with the following code:
-      </para>
-
-<programlisting>
-mysql&gt; <userinput>LOCK TABLES real_table WRITE, temp_table WRITE;</userinput>
-mysql&gt; <userinput>INSERT INTO real_table SELECT * FROM temp_table;</userinput>
-mysql&gt; <userinput>DELETE FROM temp_table;</userinput>
-mysql&gt; <userinput>UNLOCK TABLES;</userinput>
-</programlisting>
-
-      <para>
-        <literal>InnoDB</literal> uses row locks and
-        <literal>BDB</literal> uses page locks. Deadlocks are possible
-        for these storage engines because they automatically acquire
-        locks during the processing of SQL statements, not at the start
-        of the transaction.
-      </para>
-
-      <para>
-        Advantages of row-level locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Fewer lock conflicts when different sessions access
-            different rows
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Fewer changes for rollbacks
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Possible to lock a single row for a long time
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Disadvantages of row-level locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Requires more memory than page-level or table-level locks
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Slower than page-level or table-level locks when used on a
-            large part of the table because you must acquire many more
-            locks
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Slower than other locks if you often do <literal>GROUP
-            BY</literal> operations on a large part of the data or if
-            you must scan the entire table frequently
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Generally, table locks are superior to page-level or row-level
-        locks in the following cases:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Most statements for the table are reads
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Statements for the table are a mix of reads and writes,
-            where writes are updates or deletes for a single row that
-            can be fetched with one key read:
-          </para>
-
-<programlisting>
-UPDATE <replaceable>tbl_name</replaceable> SET <replaceable>column</replaceable>=<replaceable>value</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
-DELETE FROM <replaceable>tbl_name</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
-</programlisting>
-        </listitem>
-
-        <listitem>
-          <para>
-            <literal role="stmt">SELECT</literal> combined with
-            concurrent <literal role="stmt">INSERT</literal> statements,
-            and very few <literal role="stmt">UPDATE</literal> or
-            <literal role="stmt">DELETE</literal> statements
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Many scans or <literal>GROUP BY</literal> operations on the
-            entire table without any writers
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        With higher-level locks, you can more easily tune applications
-        by supporting locks of different types, because the lock
-        overhead is less than for row-level locks.
-      </para>
-
-      <para>
-        Options other than row-level or page-level locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Versioning (such as that used in MySQL for concurrent
-            inserts) where it is possible to have one writer at the same
-            time as many readers. This means that the database or table
-            supports different views for the data depending on when
-            access begins. Other common terms for this are <quote>time
-            travel,</quote> <quote>copy on write,</quote> or <quote>copy
-            on demand.</quote>
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Copy on demand is in many cases superior to page-level or
-            row-level locking. However, in the worst case, it can use
-            much more memory than using normal locks.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Instead of using row-level locks, you can employ
-            application-level locks, such as those provided by
-            <literal role="func">GET_LOCK()</literal> and
-            <literal role="func">RELEASE_LOCK()</literal> in MySQL.
-            These are advisory locks, so they work only with
-            applications that cooperate with each other. See
-            <xref linkend="miscellaneous-functions"/>.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-    </section>
-
-    <section id="table-locking">
-
-      <title>Table Locking Issues</title>
-
-      <indexterm>
-        <primary>problems</primary>
-        <secondary>table locking</secondary>
-      </indexterm>
-
-      <para>
-        To achieve a very high lock speed, MySQL uses table locking
-        (instead of page, row, or column locking) for all storage
-        engines except <literal>InnoDB</literal>,
-        <literal>BDB</literal>, and
-        <literal role="se">NDBCLUSTER</literal>.
-      </para>
-
-      <para>
-        For <literal>InnoDB</literal> and <literal>BDB</literal> tables,
-        MySQL uses table locking only if you explicitly lock the table
-        with <literal role="stmt">LOCK TABLES</literal>. For these
-        storage engines, avoid using <literal role="stmt">LOCK
-        TABLES</literal> at all, because <literal>InnoDB</literal> uses
-        automatic row-level locking and <literal>BDB</literal> uses
-        page-level locking to ensure transaction isolation.
-      </para>
-
-      <para>
-        For large tables, table locking is often better than row
-        locking, but there are some disadvantages:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Table locking enables many sessions to read from a table at
-            the same time, but if a session wants to write to a table,
-            it must first get exclusive access. During the update, all
-            other sessions that want to access this particular table
-            must wait until the update is done.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Table locking causes problems in cases such as when a
-            session is waiting because the disk is full and free space
-            needs to become available before the session can proceed. In
-            this case, all sessions that want to access the problem
-            table are also put in a waiting state until more disk space
-            is made available.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Table locking is also disadvantageous under the following
-        scenario:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            A session issues a <literal role="stmt">SELECT</literal>
-            that takes a long time to run.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Another session then issues an
-            <literal role="stmt">UPDATE</literal> on the same table.
-            This session waits until the
-            <literal role="stmt">SELECT</literal> is finished.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Another session issues another
-            <literal role="stmt">SELECT</literal> statement on the same
-            table. Because <literal role="stmt">UPDATE</literal> has
-            higher priority than <literal role="stmt">SELECT</literal>,
-            this <literal role="stmt">SELECT</literal> waits for the
-            <literal role="stmt">UPDATE</literal> to finish,
-            <emphasis>after</emphasis> waiting for the first
-            <literal role="stmt">SELECT</literal> to finish.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        The following items describe some ways to avoid or reduce
-        contention caused by table locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Try to get the <literal role="stmt">SELECT</literal>
-            statements to run faster so that they lock tables for a
-            shorter time. You might have to create some summary tables
-            to do this.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Start <command>mysqld</command> with
-            <option role="mysqld">--low-priority-updates</option>. For
-            storage engines that use only table-level locking (such as
-            <literal>MyISAM</literal>, <literal>MEMORY</literal>, and
-            <literal>MERGE</literal>), this gives all statements that
-            update (modify) a table lower priority than
-            <literal role="stmt">SELECT</literal> statements. In this
-            case, the second <literal role="stmt">SELECT</literal>
-            statement in the preceding scenario would execute before the
-            <literal role="stmt">UPDATE</literal> statement, and would
-            not need to wait for the first
-            <literal role="stmt">SELECT</literal> to finish.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            To specify that all updates issued in a specific connection
-            should be done with low priority, set the
-            <literal role="sysvar">low_priority_updates</literal> server
-            system variable equal to 1.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            To give a specific <literal role="stmt">INSERT</literal>,
-            <literal role="stmt">UPDATE</literal>, or
-            <literal role="stmt">DELETE</literal> statement lower
-            priority, use the <literal>LOW_PRIORITY</literal> attribute.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            To give a specific <literal role="stmt">SELECT</literal>
-            statement higher priority, use the
-            <literal>HIGH_PRIORITY</literal> attribute. See
-            <xref linkend="select"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Starting from MySQL 3.23.7, you can start
-            <command>mysqld</command> with a low value for the
-            <literal role="sysvar">max_write_lock_count</literal> system
-            variable to force MySQL to temporarily elevate the priority
-            of all <literal role="stmt">SELECT</literal> statements that
-            are waiting for a table after a specific number of inserts
-            to the table occur. This permits <literal>READ</literal>
-            locks after a certain number of <literal>WRITE</literal>
-            locks.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you have problems with
-            <literal role="stmt">INSERT</literal> combined with
-            <literal role="stmt">SELECT</literal>, consider switching to
-            <literal>MyISAM</literal> tables, which support concurrent
-            <literal role="stmt">SELECT</literal> and
-            <literal role="stmt">INSERT</literal> statements. (See
-            <xref linkend="concurrent-inserts"/>.)
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you mix inserts and deletes on the same table,
-            <literal role="stmt">INSERT DELAYED</literal> may be of
-            great help. See <xref linkend="insert-delayed"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you have problems with mixed
-            <literal role="stmt">SELECT</literal> and
-            <literal role="stmt">DELETE</literal> statements, the
-            <literal>LIMIT</literal> option to
-            <literal role="stmt">DELETE</literal> may help. See
-            <xref linkend="delete"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Using <literal>SQL_BUFFER_RESULT</literal> with
-            <literal role="stmt">SELECT</literal> statements can help to
-            make the duration of table locks shorter. See
-            <xref linkend="select"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            You could change the locking code in
-            <filename>mysys/thr_lock.c</filename> to use a single queue.
-            In this case, write locks and read locks would have the same
-            priority, which might help some applications.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Here are some tips concerning table locks in MySQL:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Concurrent users are not a problem if you do not mix updates
-            with selects that need to examine many rows in the same
-            table.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            You can use <literal role="stmt">LOCK TABLES</literal> to
-            increase speed, because many updates within a single lock is
-            much faster than updating without locks. Splitting table
-            contents into separate tables may also help.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you encounter speed problems with table locks in MySQL,
-            you may be able to improve performance by converting some of
-            your tables to <literal>InnoDB</literal> or
-            <literal>BDB</literal> tables. See <xref linkend="innodb"/>,
-            and <xref linkend="bdb-storage-engine"/>.
-          </para>
-
-          <formalpara role="mnmas">
-
-            <title>MySQL Enterprise</title>
-
-            <para>
-              Lock contention can seriously degrade performance. The
-              MySQL Enterprise Monitor provides expert advice on
-              avoiding this problem. To subscribe, see
-              &base-url-enterprise;advisors.html.
-            </para>
-
-          </formalpara>
-        </listitem>
-
-      </itemizedlist>
-
-    </section>
-
-    <section id="concurrent-inserts">
-
-      <title>Concurrent Inserts</title>
-
-      <indexterm>
-        <primary>concurrent inserts</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>inserts</primary>
-        <secondary>concurrent</secondary>
-      </indexterm>
-
-      <para>
-        As of MySQL 3.23.7 (3.23.25 for Windows), the
-        <literal>MyISAM</literal> storage engine supports concurrent
-        inserts to reduce contention between readers and writers for a
-        given table: If a <literal>MyISAM</literal> table has no holes
-        in the data file (deleted rows in the middle), an
-        <literal role="stmt">INSERT</literal> statement can be executed
-        to add rows to the end of the table at the same time that
-        <literal role="stmt">SELECT</literal> statements are reading
-        rows from the table. If there are multiple
-        <literal role="stmt">INSERT</literal> statements, they are
-        queued and performed in sequence, concurrently with the
-        <literal role="stmt">SELECT</literal> statements. The results of
-        a concurrent <literal role="stmt">INSERT</literal> may not be
-        visible immediately.
-      </para>
-
-      <para>
-        Concurrent inserts are enabled by default, but can be disabled
-        by setting the
-        <literal role="sysvar">concurrent_insert</literal> system
-        variable to 0.
-      </para>
-
-      <para>
-        Under circumstances where concurrent inserts can be used, there
-        is seldom any need to use the <literal>DELAYED</literal>
-        modifier for <literal role="stmt">INSERT</literal> statements.
-        See <xref linkend="insert-delayed"/>.
-      </para>
-
-      <para>
-        If you are using the update log or binary log, concurrent
-        inserts are converted to normal inserts for <literal>CREATE ...
-        SELECT</literal> or
-        <literal role="stmt" condition="insert-select">INSERT ...
-        SELECT</literal> statements. This is done to ensure that you can
-        re-create an exact copy of your tables by applying the log
-        during a backup operation. See <xref linkend="binary-log"/>. In
-        addition, for those statements a read lock is placed on the
-        selected-from table such that inserts into that table are
-        blocked. The effect is that concurrent inserts for that table
-        must wait as well.
-      </para>
-
-      <para>
-        With <literal role="stmt" condition="load-data">LOAD DATA
-        INFILE</literal>, if you specify <literal>CONCURRENT</literal>
-        with a <literal>MyISAM</literal> table that satisfies the
-        condition for concurrent inserts (that is, it contains no free
-        blocks in the middle), other sessions can retrieve data from the
-        table while <literal role="stmt">LOAD DATA</literal> is
-        executing. Use of the <literal>CONCURRENT</literal> option
-        affects the performance of <literal role="stmt">LOAD
-        DATA</literal> a bit, even if no other session is using the
-        table at the same time.
-      </para>
-
-      <para>
-        If you specify <literal>HIGH_PRIORITY</literal>, it overrides
-        the effect of the
-        <option role="mysqld">--low-priority-updates</option> option if
-        the server was started with that option. It also causes
-        concurrent inserts not to be used.
-      </para>
-
-      <para>
-        For <literal role="stmt" condition="lock-tables">LOCK
-        TABLE</literal>, the difference between <literal>READ
-        LOCAL</literal> and <literal>READ</literal> is that
-        <literal>READ LOCAL</literal> permits nonconflicting
-        <literal role="stmt">INSERT</literal> statements (concurrent
-        inserts) to execute while the lock is held. However, this cannot
-        be used if you are going to manipulate the database using
-        processes external to the server while you hold the lock.
-      </para>
-
-    </section>
-
-    <section id="external-locking">
-
-      <title>External Locking</title>
-
-      <indexterm>
-        <primary>external locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>external</secondary>
-      </indexterm>
-
-      <para>
-        External locking is the use of file system locking to manage
-        contention for database tables by multiple processes. External
-        locking is used in situations where a single process such as the
-        MySQL server cannot be assumed to be the only process that
-        requires access to tables. Here are some examples:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            If you run multiple servers that use the same database
-            directory (not recommended), each server must have external
-            locking enabled.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you use <command>myisamchk</command> to perform table
-            maintenance operations on <literal>MyISAM</literal> tables,
-            you must either ensure that the server is not running, or
-            that the server has external locking enabled so that it
-            locks table files as necessary to coordinate with
-            <command>myisamchk</command> for access to the tables. The
-            same is true for use of <command>myisampack</command> to
-            pack <literal>MyISAM</literal> tables.
-          </para>
-
-          <para>
-            If the server is run with external locking enabled, you can
-            use <command>myisamchk</command> at any time for read
-            operations such a checking tables. In this case, if the
-            server tries to update a table that
-            <command>myisamchk</command> is using, the server will wait
-            for <command>myisamchk</command> to finish before it
-            continues.
-          </para>
-
-          <para>
-            If you use <command>myisamchk</command> for write operations
-            such as repairing or optimizing tables, or if you use
-            <command>myisampack</command> to pack tables, you
-            <emphasis>must</emphasis> always ensure that the
-            <command>mysqld</command> server is not using the table. If
-            you don't stop <command>mysqld</command>, you should at
-            least do a <command>mysqladmin flush-tables</command> before
-            you run <command>myisamchk</command>. Your tables
-            <emphasis>may become corrupted</emphasis> if the server and
-            <command>myisamchk</command> access the tables
-            simultaneously.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        With external locking in effect, each process that requires
-        access to a table acquires a file system lock for the table
-        files before proceeding to access the table. If all necessary
-        locks cannot be acquired, the process is blocked from accessing
-        the table until the locks can be obtained (after the process
-        that currently holds the locks releases them).
-      </para>
-
-      <para>
-        External locking affects server performance because the server
-        must sometimes wait for other processes before it can access
-        tables.
-      </para>
-
-      <para>
-        External locking is unnecessary if you run a single server to
-        access a given data directory (which is the usual case) and if
-        no other programs such as <command>myisamchk</command> need to
-        modify tables while the server is running. If you only
-        <emphasis>read</emphasis> tables with other programs, external
-        locking is not required, although <command>myisamchk</command>
-        might report warnings if the server changes tables while
-        <command>myisamchk</command> is reading them.
-      </para>
-
-      <para>
-        With external locking disabled, to use
-        <command>myisamchk</command>, you must either stop the server
-        while <command>myisamchk</command> executes or else lock and
-        flush the tables before running <command>myisamchk</command>.
-        (See <xref linkend="system-optimization"/>.) To avoid this
-        requirement as of MySQL 3.23, use the <literal role="stmt">CHECK
-        TABLE</literal> and <literal role="stmt">REPAIR TABLE</literal>
-        statements to check and repair <literal>MyISAM</literal> tables.
-      </para>
-
-      <para>
-        For <command>mysqld</command>, external locking is controlled by
-        the value of the
-        <literal role="sysvar">skip_external_locking</literal> system
-        variable. (Before MySQL 4.0.3, this variable is named
-        <literal>skip_locking</literal>.) When this variable is enabled,
-        external locking is disabled, and vice versa. From MySQL 4.0 on,
-        external locking is disabled by default. Before MySQL 4.0,
-        external locking is enabled by default on Linux or when MySQL is
-        configured to use MIT-pthreads.
-      </para>
-
-      <para>
-        Use of external locking can be controlled at server startup by
-        using the <option role="mysqld">--external-locking</option> or
-        <option role="mysqld">--skip-external-locking</option> option.
-        (Before MySQL 4.0.3, these options are named
-        <option>--enable-locking</option> and
-        <option>--skip-locking</option>.)
-      </para>
-
-      <para>
-        If you do use external locking option to enable updates to
-        <literal>MyISAM</literal> tables from many MySQL processes, you
-        must ensure that the following conditions are satisfied:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            You should not use the query cache for queries that use
-            tables that are updated by another process.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            You should not start the server with the
-            <option role="mysqld">--delay-key-write=ALL</option> option
-            or use the <literal>DELAY_KEY_WRITE=1</literal> table option
-            for any shared tables. Otherwise, index corruption can
-            occur.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        The easiest way to satisfy these conditions is to always use
-        <option role="mysqld">--external-locking</option> together with
-        <option role="mysqld">--delay-key-write=OFF</option> and
-        <option role="sysvar">--query-cache-size=0</option>. (This is
-        not done by default because in many setups it is useful to have
-        a mixture of the preceding options.)
-      </para>
-
-    </section>
-
-  </section>
-
-  <section id="optimizing-database-structure">
-
-    <title>Optimizing Database Structure</title>
-
-    <section id="data-size">
-
-      <title>Make Your Data as Small as Possible</title>
-
-      <indexterm>
-        <primary>data</primary>
-        <secondary>size</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>reducing</primary>
-        <secondary>data size</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>storage space</primary>
-        <secondary>minimizing</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>tables</primary>
-        <secondary>improving performance</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>performance</primary>
-        <secondary>improving</secondary>
-      </indexterm>
-
-      <para>
-        One of the most basic optimizations is to design your tables to
-        take as little space on the disk as possible. This can result in
-        huge improvements because disk reads are faster, and smaller
-        tables normally require less main memory while their contents
-        are being actively processed during query execution. Indexing
-        also is a lesser resource burden if done on smaller columns.
-      </para>
-
-      <para>
-        MySQL supports many different storage engines (table types) and
-        row formats. For each table, you can decide which storage and
-        indexing method to use. Choosing the proper table format for
-        your application may give you a big performance gain. See
-        <xref linkend="storage-engines"/>.
-      </para>
-
-      <para>
-        You can get better performance for a table and minimize storage
-        space by using the techniques listed here:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Use the most efficient (smallest) data types possible. MySQL
-            has many specialized types that save disk space and memory.
-            For example, use the smaller integer types if possible to
-            get smaller tables. <literal role="type">MEDIUMINT</literal>
-            is often a better choice than
-            <literal role="type">INT</literal> because a
-            <literal role="type">MEDIUMINT</literal> column uses 25%
-            less space.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Declare columns to be <literal>NOT NULL</literal> if
-            possible. It makes everything faster and you save one bit
-            per column. If you really need <literal>NULL</literal> in
-            your application, you should definitely use it. Just avoid
-            having it on all columns by default.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            For <literal>MyISAM</literal> tables, if you do not have any
-            variable-length columns
-            (<literal role="type">VARCHAR</literal>,
-            <literal role="type">TEXT</literal>, or
-            <literal role="type">BLOB</literal> columns), a fixed-size
-            row format is used. This is faster but unfortunately may
-            waste some space. See
-            <xref linkend="myisam-table-formats"/>. You can hint that
-            you want to have fixed length rows even if you have
-            <literal role="type">VARCHAR</literal> columns with the
-            <literal role="stmt">CREATE TABLE</literal> option
-            <literal>ROW_FORMAT=FIXED</literal>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            The primary index of a table should be as short as possible.
-            This makes identification of each row easy and efficient.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Create only the indexes that you really need. Indexes are
-            good for retrieval but bad when you need to store data
-            quickly. If you access a table mostly by searching on a
-            combination of columns, create an index on them. The first
-            part of the index should be the column most used. If you
-            <emphasis>always</emphasis> use many columns when selecting
-            from the table, the first column in the index should be the
-            one with the most duplicates to obtain better compression of
-            the index.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If it is very likely that a string column has a unique
-            prefix on the first number of characters, it is better to
-            index only this prefix, using MySQL's support for creating
-            an index on the leftmost part of the column (see
-            <xref linkend="create-index"/>). Shorter indexes are faster,
-            not only because they require less disk space, but because
-            they also give you more hits in the index cache, and thus
-            fewer disk seeks. See <xref linkend="server-parameters"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            In some circumstances, it can be beneficial to split into
-            two a table that is scanned very often. This is especially
-            true if it is a dynamic-format table and it is possible to
-            use a smaller static format table that can be used to find
-            the relevant rows when scanning the table.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-    </section>
-
-    <section id="indexes">
-
       <title>Column Indexes</title>
 
       <indexterm>

@@ -6502,7 +5408,7 @@
         MySQL can create composite indexes (that is, indexes on multiple
         columns). An index may consist of up to 16 columns. For certain
         data types, you can index a prefix of the column (see
-        <xref linkend="indexes"/>).
+        <xref linkend="column-indexes"/>).
       </para>
 
       <para>

@@ -8055,6 +6961,1106 @@
 
     </section>
 
+  </section>
+
+  <section id="locking-issues">
+
+    <title>Locking Issues</title>
+
+    <para>
+      MySQL manages contention for table contents using locking:
+    </para>
+
+    <itemizedlist>
+
+      <listitem>
+        <para>
+          Internal locking is performed within the MySQL server itself
+          to manage contention for table contents by multiple threads.
+          This type of locking is internal because it is performed
+          entirely by the server and involves no other programs. See
+          <xref linkend="internal-locking"/>.
+        </para>
+      </listitem>
+
+      <listitem>
+        <para>
+          External locking occurs when the server and other programs
+          lock table files to coordinate among themselves which program
+          can access the tables at which time. See
+          <xref linkend="external-locking"/>.
+        </para>
+      </listitem>
+
+    </itemizedlist>
+
+    <section id="internal-locking">
+
+      <title>Internal Locking Methods</title>
+
+      <indexterm>
+        <primary>internal locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>internal</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking methods</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>methods</primary>
+        <secondary>locking</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>row-level locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>page-level locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>table-level locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>row-level</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>page-level</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>table-level</secondary>
+      </indexterm>
+
+      <para>
+        This section discusses internal locking; that is, locking
+        performed within the MySQL server itself to manage contention
+        for table contents by multiple sessions. This type of locking is
+        internal because it is performed entirely by the server and
+        involves no other programs. External locking occurs when the
+        server and other programs lock table files to coordinate among
+        themselves which program can access the tables at which time.
+        See <xref linkend="external-locking"/>.
+      </para>
+
+      <para>
+        MySQL uses table-level locking for <literal>ISAM</literal>,
+        <literal>MyISAM</literal>, <literal>MEMORY</literal>
+        (<literal>HEAP</literal>), and <literal>MERGE</literal> tables,
+        page-level locking for <literal>BDB</literal> tables, and
+        row-level locking for <literal>InnoDB</literal> tables.
+      </para>
+
+      <para>
+        In many cases, you can make an educated guess about which
+        locking type is best for an application, but generally it is
+        difficult to say that a given lock type is better than another.
+        Everything depends on the application and different parts of an
+        application may require different lock types.
+      </para>
+
+      <para>
+        To decide whether you want to use a storage engine with
+        row-level locking, you should look at what your application does
+        and what mix of select and update statements it uses. For
+        example, most Web applications perform many selects, relatively
+        few deletes, updates based mainly on key values, and inserts
+        into a few specific tables. The base MySQL
+        <literal>MyISAM</literal> setup is very well tuned for this.
+      </para>
+
+      <formalpara role="mnmas">
+
+        <title>MySQL Enterprise</title>
+
+        <para>
+          The MySQL Enterprise Monitor provides expert advice on when to
+          use table-level locking and when to use row-level locking. To
+          subscribe, see &base-url-enterprise;advisors.html.
+        </para>
+
+      </formalpara>
+
+      <para>
+        Table locking in MySQL is deadlock-free for storage engines that
+        use table-level locking. Deadlock avoidance is managed by always
+        requesting all needed locks at once at the beginning of a query
+        and always locking the tables in the same order.
+      </para>
+
+      <para>
+        MySQL grants table write locks as follows:
+      </para>
+
+      <orderedlist>
+
+        <listitem>
+          <para>
+            If there are no locks on the table, put a write lock on it.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Otherwise, put the lock request in the write lock queue.
+          </para>
+        </listitem>
+
+      </orderedlist>
+
+      <para>
+        MySQL grants table read locks as follows:
+      </para>
+
+      <orderedlist>
+
+        <listitem>
+          <para>
+            If there are no write locks on the table, put a read lock on
+            it.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Otherwise, put the lock request in the read lock queue.
+          </para>
+        </listitem>
+
+      </orderedlist>
+
+      <para>
+        Table updates are given higher priority than table retrievals.
+        Therefore, when a lock is released, the lock is made available
+        to the requests in the write lock queue and then to the requests
+        in the read lock queue. This ensures that updates to a table are
+        not <quote>starved</quote> even if there is heavy
+        <literal role="stmt">SELECT</literal> activity for the table.
+        However, if you have many updates for a table,
+        <literal role="stmt">SELECT</literal> statements wait until
+        there are no more updates.
+      </para>
+
+      <para>
+        For information on altering the priority of reads and writes,
+        see <xref linkend="table-locking"/>.
+      </para>
+
+      <para>
+        Starting in MySQL 3.23.33, you can analyze the table lock
+        contention on your system by checking the
+        <literal role="statvar">Table_locks_immediate</literal> and
+        <literal role="statvar">Table_locks_waited</literal> status
+        variables, which indicate the number of times that requests for
+        table locks could be granted immediately and the number that had
+        to wait, respectively:
+      </para>
+
+<programlisting>
+mysql&gt; <userinput>SHOW STATUS LIKE 'Table%';</userinput>
++-----------------------+---------+
+| Variable_name         | Value   |
++-----------------------+---------+
+| Table_locks_immediate | 1151552 |
+| Table_locks_waited    | 15324   |
++-----------------------+---------+
+</programlisting>
+
+      <indexterm>
+        <primary>concurrent inserts</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>inserts</primary>
+        <secondary>concurrent</secondary>
+      </indexterm>
+
+      <para>
+        As of MySQL 3.23.7 (3.23.25 for Windows), the
+        <literal>MyISAM</literal> storage engine supports concurrent
+        inserts to reduce contention between readers and writers for a
+        given table: If a <literal>MyISAM</literal> table has no free
+        blocks in the middle of the data file, rows are always inserted
+        at the end of the data file. In this case, you can freely mix
+        concurrent <literal role="stmt">INSERT</literal> and
+        <literal role="stmt">SELECT</literal> statements for a
+        <literal>MyISAM</literal> table without locks. That is, you can
+        insert rows into a <literal>MyISAM</literal> table at the same
+        time other clients are reading from it. (Holes can result from
+        rows having been deleted from or updated in the middle of the
+        table. If there are holes, concurrent inserts are disabled but
+        are enabled again automatically when all holes have been filled
+        with new data.)
+      </para>
+
+      <para>
+        If you acquire a table lock explicitly with
+        <literal role="stmt">LOCK TABLES</literal>, you can request a
+        <literal>READ LOCAL</literal> lock rather than a
+        <literal>READ</literal> lock to enable other sessions to perform
+        concurrent inserts while you have the table locked.
+      </para>
+
+      <para>
+        To perform many <literal role="stmt">INSERT</literal> and
+        <literal role="stmt">SELECT</literal> operations on a table
+        <literal>real_table</literal> when concurrent inserts are not
+        possible, you can insert rows into a temporary table
+        <literal>temp_table</literal> and update the real table with the
+        rows from the temporary table periodically. This can be done
+        with the following code:
+      </para>
+
+<programlisting>
+mysql&gt; <userinput>LOCK TABLES real_table WRITE, temp_table WRITE;</userinput>
+mysql&gt; <userinput>INSERT INTO real_table SELECT * FROM temp_table;</userinput>
+mysql&gt; <userinput>DELETE FROM temp_table;</userinput>
+mysql&gt; <userinput>UNLOCK TABLES;</userinput>
+</programlisting>
+
+      <para>
+        <literal>InnoDB</literal> uses row locks and
+        <literal>BDB</literal> uses page locks. Deadlocks are possible
+        for these storage engines because they automatically acquire
+        locks during the processing of SQL statements, not at the start
+        of the transaction.
+      </para>
+
+      <para>
+        Advantages of row-level locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Fewer lock conflicts when different sessions access
+            different rows
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Fewer changes for rollbacks
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Possible to lock a single row for a long time
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Disadvantages of row-level locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Requires more memory than page-level or table-level locks
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Slower than page-level or table-level locks when used on a
+            large part of the table because you must acquire many more
+            locks
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Slower than other locks if you often do <literal>GROUP
+            BY</literal> operations on a large part of the data or if
+            you must scan the entire table frequently
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Generally, table locks are superior to page-level or row-level
+        locks in the following cases:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Most statements for the table are reads
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Statements for the table are a mix of reads and writes,
+            where writes are updates or deletes for a single row that
+            can be fetched with one key read:
+          </para>
+
+<programlisting>
+UPDATE <replaceable>tbl_name</replaceable> SET <replaceable>column</replaceable>=<replaceable>value</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
+DELETE FROM <replaceable>tbl_name</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
+</programlisting>
+        </listitem>
+
+        <listitem>
+          <para>
+            <literal role="stmt">SELECT</literal> combined with
+            concurrent <literal role="stmt">INSERT</literal> statements,
+            and very few <literal role="stmt">UPDATE</literal> or
+            <literal role="stmt">DELETE</literal> statements
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Many scans or <literal>GROUP BY</literal> operations on the
+            entire table without any writers
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        With higher-level locks, you can more easily tune applications
+        by supporting locks of different types, because the lock
+        overhead is less than for row-level locks.
+      </para>
+
+      <para>
+        Options other than row-level or page-level locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Versioning (such as that used in MySQL for concurrent
+            inserts) where it is possible to have one writer at the same
+            time as many readers. This means that the database or table
+            supports different views for the data depending on when
+            access begins. Other common terms for this are <quote>time
+            travel,</quote> <quote>copy on write,</quote> or <quote>copy
+            on demand.</quote>
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Copy on demand is in many cases superior to page-level or
+            row-level locking. However, in the worst case, it can use
+            much more memory than using normal locks.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Instead of using row-level locks, you can employ
+            application-level locks, such as those provided by
+            <literal role="func">GET_LOCK()</literal> and
+            <literal role="func">RELEASE_LOCK()</literal> in MySQL.
+            These are advisory locks, so they work only with
+            applications that cooperate with each other. See
+            <xref linkend="miscellaneous-functions"/>.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+    </section>
+
+    <section id="table-locking">
+
+      <title>Table Locking Issues</title>
+
+      <indexterm>
+        <primary>problems</primary>
+        <secondary>table locking</secondary>
+      </indexterm>
+
+      <para>
+        To achieve a very high lock speed, MySQL uses table locking
+        (instead of page, row, or column locking) for all storage
+        engines except <literal>InnoDB</literal>,
+        <literal>BDB</literal>, and
+        <literal role="se">NDBCLUSTER</literal>.
+      </para>
+
+      <para>
+        For <literal>InnoDB</literal> and <literal>BDB</literal> tables,
+        MySQL uses table locking only if you explicitly lock the table
+        with <literal role="stmt">LOCK TABLES</literal>. For these
+        storage engines, avoid using <literal role="stmt">LOCK
+        TABLES</literal> at all, because <literal>InnoDB</literal> uses
+        automatic row-level locking and <literal>BDB</literal> uses
+        page-level locking to ensure transaction isolation.
+      </para>
+
+      <para>
+        For large tables, table locking is often better than row
+        locking, but there are some disadvantages:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Table locking enables many sessions to read from a table at
+            the same time, but if a session wants to write to a table,
+            it must first get exclusive access. During the update, all
+            other sessions that want to access this particular table
+            must wait until the update is done.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Table locking causes problems in cases such as when a
+            session is waiting because the disk is full and free space
+            needs to become available before the session can proceed. In
+            this case, all sessions that want to access the problem
+            table are also put in a waiting state until more disk space
+            is made available.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Table locking is also disadvantageous under the following
+        scenario:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            A session issues a <literal role="stmt">SELECT</literal>
+            that takes a long time to run.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Another session then issues an
+            <literal role="stmt">UPDATE</literal> on the same table.
+            This session waits until the
+            <literal role="stmt">SELECT</literal> is finished.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Another session issues another
+            <literal role="stmt">SELECT</literal> statement on the same
+            table. Because <literal role="stmt">UPDATE</literal> has
+            higher priority than <literal role="stmt">SELECT</literal>,
+            this <literal role="stmt">SELECT</literal> waits for the
+            <literal role="stmt">UPDATE</literal> to finish,
+            <emphasis>after</emphasis> waiting for the first
+            <literal role="stmt">SELECT</literal> to finish.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        The following items describe some ways to avoid or reduce
+        contention caused by table locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Try to get the <literal role="stmt">SELECT</literal>
+            statements to run faster so that they lock tables for a
+            shorter time. You might have to create some summary tables
+            to do this.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Start <command>mysqld</command> with
+            <option role="mysqld">--low-priority-updates</option>. For
+            storage engines that use only table-level locking (such as
+            <literal>MyISAM</literal>, <literal>MEMORY</literal>, and
+            <literal>MERGE</literal>), this gives all statements that
+            update (modify) a table lower priority than
+            <literal role="stmt">SELECT</literal> statements. In this
+            case, the second <literal role="stmt">SELECT</literal>
+            statement in the preceding scenario would execute before the
+            <literal role="stmt">UPDATE</literal> statement, and would
+            not need to wait for the first
+            <literal role="stmt">SELECT</literal> to finish.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            To specify that all updates issued in a specific connection
+            should be done with low priority, set the
+            <literal role="sysvar">low_priority_updates</literal> server
+            system variable equal to 1.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            To give a specific <literal role="stmt">INSERT</literal>,
+            <literal role="stmt">UPDATE</literal>, or
+            <literal role="stmt">DELETE</literal> statement lower
+            priority, use the <literal>LOW_PRIORITY</literal> attribute.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            To give a specific <literal role="stmt">SELECT</literal>
+            statement higher priority, use the
+            <literal>HIGH_PRIORITY</literal> attribute. See
+            <xref linkend="select"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Starting from MySQL 3.23.7, you can start
+            <command>mysqld</command> with a low value for the
+            <literal role="sysvar">max_write_lock_count</literal> system
+            variable to force MySQL to temporarily elevate the priority
+            of all <literal role="stmt">SELECT</literal> statements that
+            are waiting for a table after a specific number of inserts
+            to the table occur. This permits <literal>READ</literal>
+            locks after a certain number of <literal>WRITE</literal>
+            locks.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you have problems with
+            <literal role="stmt">INSERT</literal> combined with
+            <literal role="stmt">SELECT</literal>, consider switching to
+            <literal>MyISAM</literal> tables, which support concurrent
+            <literal role="stmt">SELECT</literal> and
+            <literal role="stmt">INSERT</literal> statements. (See
+            <xref linkend="concurrent-inserts"/>.)
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you mix inserts and deletes on the same table,
+            <literal role="stmt">INSERT DELAYED</literal> may be of
+            great help. See <xref linkend="insert-delayed"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you have problems with mixed
+            <literal role="stmt">SELECT</literal> and
+            <literal role="stmt">DELETE</literal> statements, the
+            <literal>LIMIT</literal> option to
+            <literal role="stmt">DELETE</literal> may help. See
+            <xref linkend="delete"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Using <literal>SQL_BUFFER_RESULT</literal> with
+            <literal role="stmt">SELECT</literal> statements can help to
+            make the duration of table locks shorter. See
+            <xref linkend="select"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            You could change the locking code in
+            <filename>mysys/thr_lock.c</filename> to use a single queue.
+            In this case, write locks and read locks would have the same
+            priority, which might help some applications.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Here are some tips concerning table locks in MySQL:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Concurrent users are not a problem if you do not mix updates
+            with selects that need to examine many rows in the same
+            table.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            You can use <literal role="stmt">LOCK TABLES</literal> to
+            increase speed, because many updates within a single lock is
+            much faster than updating without locks. Splitting table
+            contents into separate tables may also help.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you encounter speed problems with table locks in MySQL,
+            you may be able to improve performance by converting some of
+            your tables to <literal>InnoDB</literal> or
+            <literal>BDB</literal> tables. See <xref linkend="innodb"/>,
+            and <xref linkend="bdb-storage-engine"/>.
+          </para>
+
+          <formalpara role="mnmas">
+
+            <title>MySQL Enterprise</title>
+
+            <para>
+              Lock contention can seriously degrade performance. The
+              MySQL Enterprise Monitor provides expert advice on
+              avoiding this problem. To subscribe, see
+              &base-url-enterprise;advisors.html.
+            </para>
+
+          </formalpara>
+        </listitem>
+
+      </itemizedlist>
+
+    </section>
+
+    <section id="concurrent-inserts">
+
+      <title>Concurrent Inserts</title>
+
+      <indexterm>
+        <primary>concurrent inserts</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>inserts</primary>
+        <secondary>concurrent</secondary>
+      </indexterm>
+
+      <para>
+        As of MySQL 3.23.7 (3.23.25 for Windows), the
+        <literal>MyISAM</literal> storage engine supports concurrent
+        inserts to reduce contention between readers and writers for a
+        given table: If a <literal>MyISAM</literal> table has no holes
+        in the data file (deleted rows in the middle), an
+        <literal role="stmt">INSERT</literal> statement can be executed
+        to add rows to the end of the table at the same time that
+        <literal role="stmt">SELECT</literal> statements are reading
+        rows from the table. If there are multiple
+        <literal role="stmt">INSERT</literal> statements, they are
+        queued and performed in sequence, concurrently with the
+        <literal role="stmt">SELECT</literal> statements. The results of
+        a concurrent <literal role="stmt">INSERT</literal> may not be
+        visible immediately.
+      </para>
+
+      <para>
+        Concurrent inserts are enabled by default, but can be disabled
+        by setting the
+        <literal role="sysvar">concurrent_insert</literal> system
+        variable to 0.
+      </para>
+
+      <para>
+        Under circumstances where concurrent inserts can be used, there
+        is seldom any need to use the <literal>DELAYED</literal>
+        modifier for <literal role="stmt">INSERT</literal> statements.
+        See <xref linkend="insert-delayed"/>.
+      </para>
+
+      <para>
+        If you are using the update log or binary log, concurrent
+        inserts are converted to normal inserts for <literal>CREATE ...
+        SELECT</literal> or
+        <literal role="stmt" condition="insert-select">INSERT ...
+        SELECT</literal> statements. This is done to ensure that you can
+        re-create an exact copy of your tables by applying the log
+        during a backup operation. See <xref linkend="binary-log"/>. In
+        addition, for those statements a read lock is placed on the
+        selected-from table such that inserts into that table are
+        blocked. The effect is that concurrent inserts for that table
+        must wait as well.
+      </para>
+
+      <para>
+        With <literal role="stmt" condition="load-data">LOAD DATA
+        INFILE</literal>, if you specify <literal>CONCURRENT</literal>
+        with a <literal>MyISAM</literal> table that satisfies the
+        condition for concurrent inserts (that is, it contains no free
+        blocks in the middle), other sessions can retrieve data from the
+        table while <literal role="stmt">LOAD DATA</literal> is
+        executing. Use of the <literal>CONCURRENT</literal> option
+        affects the performance of <literal role="stmt">LOAD
+        DATA</literal> a bit, even if no other session is using the
+        table at the same time.
+      </para>
+
+      <para>
+        If you specify <literal>HIGH_PRIORITY</literal>, it overrides
+        the effect of the
+        <option role="mysqld">--low-priority-updates</option> option if
+        the server was started with that option. It also causes
+        concurrent inserts not to be used.
+      </para>
+
+      <para>
+        For <literal role="stmt" condition="lock-tables">LOCK
+        TABLE</literal>, the difference between <literal>READ
+        LOCAL</literal> and <literal>READ</literal> is that
+        <literal>READ LOCAL</literal> permits nonconflicting
+        <literal role="stmt">INSERT</literal> statements (concurrent
+        inserts) to execute while the lock is held. However, this cannot
+        be used if you are going to manipulate the database using
+        processes external to the server while you hold the lock.
+      </para>
+
+    </section>
+
+    <section id="external-locking">
+
+      <title>External Locking</title>
+
+      <indexterm>
+        <primary>external locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>external</secondary>
+      </indexterm>
+
+      <para>
+        External locking is the use of file system locking to manage
+        contention for database tables by multiple processes. External
+        locking is used in situations where a single process such as the
+        MySQL server cannot be assumed to be the only process that
+        requires access to tables. Here are some examples:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            If you run multiple servers that use the same database
+            directory (not recommended), each server must have external
+            locking enabled.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you use <command>myisamchk</command> to perform table
+            maintenance operations on <literal>MyISAM</literal> tables,
+            you must either ensure that the server is not running, or
+            that the server has external locking enabled so that it
+            locks table files as necessary to coordinate with
+            <command>myisamchk</command> for access to the tables. The
+            same is true for use of <command>myisampack</command> to
+            pack <literal>MyISAM</literal> tables.
+          </para>
+
+          <para>
+            If the server is run with external locking enabled, you can
+            use <command>myisamchk</command> at any time for read
+            operations such a checking tables. In this case, if the
+            server tries to update a table that
+            <command>myisamchk</command> is using, the server will wait
+            for <command>myisamchk</command> to finish before it
+            continues.
+          </para>
+
+          <para>
+            If you use <command>myisamchk</command> for write operations
+            such as repairing or optimizing tables, or if you use
+            <command>myisampack</command> to pack tables, you
+            <emphasis>must</emphasis> always ensure that the
+            <command>mysqld</command> server is not using the table. If
+            you don't stop <command>mysqld</command>, you should at
+            least do a <command>mysqladmin flush-tables</command> before
+            you run <command>myisamchk</command>. Your tables
+            <emphasis>may become corrupted</emphasis> if the server and
+            <command>myisamchk</command> access the tables
+            simultaneously.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        With external locking in effect, each process that requires
+        access to a table acquires a file system lock for the table
+        files before proceeding to access the table. If all necessary
+        locks cannot be acquired, the process is blocked from accessing
+        the table until the locks can be obtained (after the process
+        that currently holds the locks releases them).
+      </para>
+
+      <para>
+        External locking affects server performance because the server
+        must sometimes wait for other processes before it can access
+        tables.
+      </para>
+
+      <para>
+        External locking is unnecessary if you run a single server to
+        access a given data directory (which is the usual case) and if
+        no other programs such as <command>myisamchk</command> need to
+        modify tables while the server is running. If you only
+        <emphasis>read</emphasis> tables with other programs, external
+        locking is not required, although <command>myisamchk</command>
+        might report warnings if the server changes tables while
+        <command>myisamchk</command> is reading them.
+      </para>
+
+      <para>
+        With external locking disabled, to use
+        <command>myisamchk</command>, you must either stop the server
+        while <command>myisamchk</command> executes or else lock and
+        flush the tables before running <command>myisamchk</command>.
+        (See <xref linkend="system-optimization"/>.) To avoid this
+        requirement as of MySQL 3.23, use the <literal role="stmt">CHECK
+        TABLE</literal> and <literal role="stmt">REPAIR TABLE</literal>
+        statements to check and repair <literal>MyISAM</literal> tables.
+      </para>
+
+      <para>
+        For <command>mysqld</command>, external locking is controlled by
+        the value of the
+        <literal role="sysvar">skip_external_locking</literal> system
+        variable. (Before MySQL 4.0.3, this variable is named
+        <literal>skip_locking</literal>.) When this variable is enabled,
+        external locking is disabled, and vice versa. From MySQL 4.0 on,
+        external locking is disabled by default. Before MySQL 4.0,
+        external locking is enabled by default on Linux or when MySQL is
+        configured to use MIT-pthreads.
+      </para>
+
+      <para>
+        Use of external locking can be controlled at server startup by
+        using the <option role="mysqld">--external-locking</option> or
+        <option role="mysqld">--skip-external-locking</option> option.
+        (Before MySQL 4.0.3, these options are named
+        <option>--enable-locking</option> and
+        <option>--skip-locking</option>.)
+      </para>
+
+      <para>
+        If you do use external locking option to enable updates to
+        <literal>MyISAM</literal> tables from many MySQL processes, you
+        must ensure that the following conditions are satisfied:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            You should not use the query cache for queries that use
+            tables that are updated by another process.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            You should not start the server with the
+            <option role="mysqld">--delay-key-write=ALL</option> option
+            or use the <literal>DELAY_KEY_WRITE=1</literal> table option
+            for any shared tables. Otherwise, index corruption can
+            occur.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        The easiest way to satisfy these conditions is to always use
+        <option role="mysqld">--external-locking</option> together with
+        <option role="mysqld">--delay-key-write=OFF</option> and
+        <option role="sysvar">--query-cache-size=0</option>. (This is
+        not done by default because in many setups it is useful to have
+        a mixture of the preceding options.)
+      </para>
+
+    </section>
+
+  </section>
+
+  <section id="optimizing-database-structure">
+
+    <title>Optimizing Database Structure</title>
+
+    <section id="data-size">
+
+      <title>Make Your Data as Small as Possible</title>
+
+      <indexterm>
+        <primary>data</primary>
+        <secondary>size</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>reducing</primary>
+        <secondary>data size</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>storage space</primary>
+        <secondary>minimizing</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>tables</primary>
+        <secondary>improving performance</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>performance</primary>
+        <secondary>improving</secondary>
+      </indexterm>
+
+      <para>
+        One of the most basic optimizations is to design your tables to
+        take as little space on the disk as possible. This can result in
+        huge improvements because disk reads are faster, and smaller
+        tables normally require less main memory while their contents
+        are being actively processed during query execution. Indexing
+        also is a lesser resource burden if done on smaller columns.
+      </para>
+
+      <para>
+        MySQL supports many different storage engines (table types) and
+        row formats. For each table, you can decide which storage and
+        indexing method to use. Choosing the proper table format for
+        your application may give you a big performance gain. See
+        <xref linkend="storage-engines"/>.
+      </para>
+
+      <para>
+        You can get better performance for a table and minimize storage
+        space by using the techniques listed here:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Use the most efficient (smallest) data types possible. MySQL
+            has many specialized types that save disk space and memory.
+            For example, use the smaller integer types if possible to
+            get smaller tables. <literal role="type">MEDIUMINT</literal>
+            is often a better choice than
+            <literal role="type">INT</literal> because a
+            <literal role="type">MEDIUMINT</literal> column uses 25%
+            less space.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Declare columns to be <literal>NOT NULL</literal> if
+            possible. It makes everything faster and you save one bit
+            per column. If you really need <literal>NULL</literal> in
+            your application, you should definitely use it. Just avoid
+            having it on all columns by default.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            For <literal>MyISAM</literal> tables, if you do not have any
+            variable-length columns
+            (<literal role="type">VARCHAR</literal>,
+            <literal role="type">TEXT</literal>, or
+            <literal role="type">BLOB</literal> columns), a fixed-size
+            row format is used. This is faster but unfortunately may
+            waste some space. See
+            <xref linkend="myisam-table-formats"/>. You can hint that
+            you want to have fixed length rows even if you have
+            <literal role="type">VARCHAR</literal> columns with the
+            <literal role="stmt">CREATE TABLE</literal> option
+            <literal>ROW_FORMAT=FIXED</literal>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            The primary index of a table should be as short as possible.
+            This makes identification of each row easy and efficient.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Create only the indexes that you really need. Indexes are
+            good for retrieval but bad when you need to store data
+            quickly. If you access a table mostly by searching on a
+            combination of columns, create an index on them. The first
+            part of the index should be the column most used. If you
+            <emphasis>always</emphasis> use many columns when selecting
+            from the table, the first column in the index should be the
+            one with the most duplicates to obtain better compression of
+            the index.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If it is very likely that a string column has a unique
+            prefix on the first number of characters, it is better to
+            index only this prefix, using MySQL's support for creating
+            an index on the leftmost part of the column (see
+            <xref linkend="create-index"/>). Shorter indexes are faster,
+            not only because they require less disk space, but because
+            they also give you more hits in the index cache, and thus
+            fewer disk seeks. See <xref linkend="server-parameters"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            In some circumstances, it can be beneficial to split into
+            two a table that is scanned very often. This is especially
+            true if it is a dynamic-format table and it is possible to
+            use a smaller static format table that can be used to find
+            the relevant rows when scanning the table.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+    </section>
+
     <section id="table-cache">
 
       <title>How MySQL Opens and Closes Tables</title>


Modified: trunk/refman-4.1/renamed-nodes.txt
===================================================================
--- trunk/refman-4.1/renamed-nodes.txt	2010-07-14 15:11:37 UTC (rev 21727)
+++ trunk/refman-4.1/renamed-nodes.txt	2010-07-14 15:35:58 UTC (rev 21728)
Changed blocks: 1, Lines Added: 1, Lines Deleted: 0; 614 bytes

@@ -38,6 +38,7 @@
 drop-function drop-function-udf 2009-08-01
 eiffel apis-eiffel 2009-09-01
 group-by-hidden-fields group-by-hidden-columns 2010-01-01
+indexes column-indexes 2011-07-14
 innodb-and-autocommit innodb-transaction-model 2009-11-24
 innodb-consistent-read-example innodb-consistent-read 2010-03-10
 innodb-general-monitor innodb-monitors 2010-11-05


Modified: trunk/refman-4.1/sql-syntax-data-definition.xml
===================================================================
--- trunk/refman-4.1/sql-syntax-data-definition.xml	2010-07-14 15:11:37 UTC (rev 21727)
+++ trunk/refman-4.1/sql-syntax-data-definition.xml	2010-07-14 15:35:58 UTC (rev 21728)
Changed blocks: 1, Lines Added: 1, Lines Deleted: 1; 663 bytes

@@ -2241,7 +2241,7 @@
           <literal role="type">VARBINARY</literal>, and
           <literal role="type">BLOB</literal> columns. Indexing only a
           prefix of column values like this can make the index file much
-          smaller. See <xref linkend="indexes"/>.
+          smaller. See <xref linkend="column-indexes"/>.
         </para>
 
         <indexterm>


Modified: trunk/refman-5.0/data-types.xml
===================================================================
--- trunk/refman-5.0/data-types.xml	2010-07-14 15:11:37 UTC (rev 21727)
+++ trunk/refman-5.0/data-types.xml	2010-07-14 15:35:58 UTC (rev 21728)
Changed blocks: 1, Lines Added: 1, Lines Deleted: 1; 594 bytes

@@ -4922,7 +4922,7 @@
             specify an index prefix length. For
             <literal role="type">CHAR</literal> and
             <literal role="type">VARCHAR</literal>, a prefix length is
-            optional. See <xref linkend="indexes"/>.
+            optional. See <xref linkend="column-indexes"/>.
           </para>
         </listitem>
 


Modified: trunk/refman-5.0/optimization.xml
===================================================================
--- trunk/refman-5.0/optimization.xml	2010-07-14 15:11:37 UTC (rev 21727)
+++ trunk/refman-5.0/optimization.xml	2010-07-14 15:35:58 UTC (rev 21728)
Changed blocks: 3, Lines Added: 1147, Lines Deleted: 1141; 84433 bytes

@@ -7609,1149 +7609,12 @@
 
   </section>
 
-  <section id="locking-issues">
+  <section id="optimization-indexes">
 
-    <title>Locking Issues</title>
+    <title>Optimization and Indexes</title>
 
-    <para>
-      MySQL manages contention for table contents using locking:
-    </para>
+    <section id="column-indexes">
 
-    <itemizedlist>
-
-      <listitem>
-        <para>
-          Internal locking is performed within the MySQL server itself
-          to manage contention for table contents by multiple threads.
-          This type of locking is internal because it is performed
-          entirely by the server and involves no other programs. See
-          <xref linkend="internal-locking"/>.
-        </para>
-      </listitem>
-
-      <listitem>
-        <para>
-          External locking occurs when the server and other programs
-          lock table files to coordinate among themselves which program
-          can access the tables at which time. See
-          <xref linkend="external-locking"/>.
-        </para>
-      </listitem>
-
-    </itemizedlist>
-
-    <section id="internal-locking">
-
-      <title>Internal Locking Methods</title>
-
-      <indexterm>
-        <primary>internal locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>internal</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking methods</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>methods</primary>
-        <secondary>locking</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>row-level locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>page-level locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>table-level locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>row-level</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>page-level</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>table-level</secondary>
-      </indexterm>
-
-      <para>
-        This section discusses internal locking; that is, locking
-        performed within the MySQL server itself to manage contention
-        for table contents by multiple sessions. This type of locking is
-        internal because it is performed entirely by the server and
-        involves no other programs. External locking occurs when the
-        server and other programs lock table files to coordinate among
-        themselves which program can access the tables at which time.
-        See <xref linkend="external-locking"/>.
-      </para>
-
-      <para>
-        MySQL uses table-level locking for <literal>MyISAM</literal>,
-        <literal>MEMORY</literal> and <literal>MERGE</literal> tables,
-        page-level locking for <literal>BDB</literal> tables, and
-        row-level locking for <literal>InnoDB</literal> tables.
-      </para>
-
-      <para>
-        In many cases, you can make an educated guess about which
-        locking type is best for an application, but generally it is
-        difficult to say that a given lock type is better than another.
-        Everything depends on the application and different parts of an
-        application may require different lock types.
-      </para>
-
-      <para>
-        To decide whether you want to use a storage engine with
-        row-level locking, you should look at what your application does
-        and what mix of select and update statements it uses. For
-        example, most Web applications perform many selects, relatively
-        few deletes, updates based mainly on key values, and inserts
-        into a few specific tables. The base MySQL
-        <literal>MyISAM</literal> setup is very well tuned for this.
-      </para>
-
-      <formalpara role="mnmas">
-
-        <title>MySQL Enterprise</title>
-
-        <para>
-          The MySQL Enterprise Monitor provides expert advice on when to
-          use table-level locking and when to use row-level locking. To
-          subscribe, see &base-url-enterprise;advisors.html.
-        </para>
-
-      </formalpara>
-
-      <para>
-        Table locking in MySQL is deadlock-free for storage engines that
-        use table-level locking. Deadlock avoidance is managed by always
-        requesting all needed locks at once at the beginning of a query
-        and always locking the tables in the same order.
-      </para>
-
-      <para>
-        MySQL grants table write locks as follows:
-      </para>
-
-      <orderedlist>
-
-        <listitem>
-          <para>
-            If there are no locks on the table, put a write lock on it.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Otherwise, put the lock request in the write lock queue.
-          </para>
-        </listitem>
-
-      </orderedlist>
-
-      <para>
-        MySQL grants table read locks as follows:
-      </para>
-
-      <orderedlist>
-
-        <listitem>
-          <para>
-            If there are no write locks on the table, put a read lock on
-            it.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Otherwise, put the lock request in the read lock queue.
-          </para>
-        </listitem>
-
-      </orderedlist>
-
-      <para>
-        Table updates are given higher priority than table retrievals.
-        Therefore, when a lock is released, the lock is made available
-        to the requests in the write lock queue and then to the requests
-        in the read lock queue. This ensures that updates to a table are
-        not <quote>starved</quote> even if there is heavy
-        <literal role="stmt">SELECT</literal> activity for the table.
-        However, if you have many updates for a table,
-        <literal role="stmt">SELECT</literal> statements wait until
-        there are no more updates.
-      </para>
-
-      <para>
-        For information on altering the priority of reads and writes,
-        see <xref linkend="table-locking"/>.
-      </para>
-
-      <para>
-        You can analyze the table lock contention on your system by
-        checking the
-        <literal role="statvar">Table_locks_immediate</literal> and
-        <literal role="statvar">Table_locks_waited</literal> status
-        variables, which indicate the number of times that requests for
-        table locks could be granted immediately and the number that had
-        to wait, respectively:
-      </para>
-
-<programlisting>
-mysql&gt; <userinput>SHOW STATUS LIKE 'Table%';</userinput>
-+-----------------------+---------+
-| Variable_name         | Value   |
-+-----------------------+---------+
-| Table_locks_immediate | 1151552 |
-| Table_locks_waited    | 15324   |
-+-----------------------+---------+
-</programlisting>
-
-      <indexterm>
-        <primary>concurrent inserts</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>inserts</primary>
-        <secondary>concurrent</secondary>
-      </indexterm>
-
-      <para>
-        The <literal>MyISAM</literal> storage engine supports concurrent
-        inserts to reduce contention between readers and writers for a
-        given table: If a <literal>MyISAM</literal> table has no free
-        blocks in the middle of the data file, rows are always inserted
-        at the end of the data file. In this case, you can freely mix
-        concurrent <literal role="stmt">INSERT</literal> and
-        <literal role="stmt">SELECT</literal> statements for a
-        <literal>MyISAM</literal> table without locks. That is, you can
-        insert rows into a <literal>MyISAM</literal> table at the same
-        time other clients are reading from it. Holes can result from
-        rows having been deleted from or updated in the middle of the
-        table. If there are holes, concurrent inserts are disabled but
-        are enabled again automatically when all holes have been filled
-        with new data. This behavior is altered by the
-        <literal role="sysvar">concurrent_insert</literal> system
-        variable. See <xref linkend="concurrent-inserts"/>.
-      </para>
-
-      <para>
-        If you acquire a table lock explicitly with
-        <literal role="stmt">LOCK TABLES</literal>, you can request a
-        <literal>READ LOCAL</literal> lock rather than a
-        <literal>READ</literal> lock to enable other sessions to perform
-        concurrent inserts while you have the table locked.
-      </para>
-
-      <para>
-        To perform many <literal role="stmt">INSERT</literal> and
-        <literal role="stmt">SELECT</literal> operations on a table
-        <literal>real_table</literal> when concurrent inserts are not
-        possible, you can insert rows into a temporary table
-        <literal>temp_table</literal> and update the real table with the
-        rows from the temporary table periodically. This can be done
-        with the following code:
-      </para>
-
-<programlisting>
-mysql&gt; <userinput>LOCK TABLES real_table WRITE, temp_table WRITE;</userinput>
-mysql&gt; <userinput>INSERT INTO real_table SELECT * FROM temp_table;</userinput>
-mysql&gt; <userinput>DELETE FROM temp_table;</userinput>
-mysql&gt; <userinput>UNLOCK TABLES;</userinput>
-</programlisting>
-
-      <para>
-        <literal>InnoDB</literal> uses row locks and
-        <literal>BDB</literal> uses page locks. Deadlocks are possible
-        for these storage engines because they automatically acquire
-        locks during the processing of SQL statements, not at the start
-        of the transaction.
-      </para>
-
-      <para>
-        Advantages of row-level locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Fewer lock conflicts when different sessions access
-            different rows
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Fewer changes for rollbacks
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Possible to lock a single row for a long time
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Disadvantages of row-level locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Requires more memory than page-level or table-level locks
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Slower than page-level or table-level locks when used on a
-            large part of the table because you must acquire many more
-            locks
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Slower than other locks if you often do <literal>GROUP
-            BY</literal> operations on a large part of the data or if
-            you must scan the entire table frequently
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Generally, table locks are superior to page-level or row-level
-        locks in the following cases:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Most statements for the table are reads
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Statements for the table are a mix of reads and writes,
-            where writes are updates or deletes for a single row that
-            can be fetched with one key read:
-          </para>
-
-<programlisting>
-UPDATE <replaceable>tbl_name</replaceable> SET <replaceable>column</replaceable>=<replaceable>value</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
-DELETE FROM <replaceable>tbl_name</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
-</programlisting>
-        </listitem>
-
-        <listitem>
-          <para>
-            <literal role="stmt">SELECT</literal> combined with
-            concurrent <literal role="stmt">INSERT</literal> statements,
-            and very few <literal role="stmt">UPDATE</literal> or
-            <literal role="stmt">DELETE</literal> statements
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Many scans or <literal>GROUP BY</literal> operations on the
-            entire table without any writers
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        With higher-level locks, you can more easily tune applications
-        by supporting locks of different types, because the lock
-        overhead is less than for row-level locks.
-      </para>
-
-      <para>
-        Options other than row-level or page-level locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Versioning (such as that used in MySQL for concurrent
-            inserts) where it is possible to have one writer at the same
-            time as many readers. This means that the database or table
-            supports different views for the data depending on when
-            access begins. Other common terms for this are <quote>time
-            travel,</quote> <quote>copy on write,</quote> or <quote>copy
-            on demand.</quote>
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Copy on demand is in many cases superior to page-level or
-            row-level locking. However, in the worst case, it can use
-            much more memory than using normal locks.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Instead of using row-level locks, you can employ
-            application-level locks, such as those provided by
-            <literal role="func">GET_LOCK()</literal> and
-            <literal role="func">RELEASE_LOCK()</literal> in MySQL.
-            These are advisory locks, so they work only with
-            applications that cooperate with each other. See
-            <xref linkend="miscellaneous-functions"/>.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-    </section>
-
-    <section id="table-locking">
-
-      <title>Table Locking Issues</title>
-
-      <indexterm>
-        <primary>problems</primary>
-        <secondary>table locking</secondary>
-      </indexterm>
-
-      <para>
-        To achieve a very high lock speed, MySQL uses table locking
-        (instead of page, row, or column locking) for all storage
-        engines except <literal>InnoDB</literal>,
-        <literal>BDB</literal>, and
-        <literal role="se">NDBCLUSTER</literal>.
-      </para>
-
-      <para>
-        For <literal>InnoDB</literal> and <literal>BDB</literal> tables,
-        MySQL uses table locking only if you explicitly lock the table
-        with <literal role="stmt">LOCK TABLES</literal>. For these
-        storage engines, avoid using <literal role="stmt">LOCK
-        TABLES</literal> at all, because <literal>InnoDB</literal> uses
-        automatic row-level locking and <literal>BDB</literal> uses
-        page-level locking to ensure transaction isolation.
-      </para>
-
-      <para>
-        For large tables, table locking is often better than row
-        locking, but there are some disadvantages:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Table locking enables many sessions to read from a table at
-            the same time, but if a session wants to write to a table,
-            it must first get exclusive access. During the update, all
-            other sessions that want to access this particular table
-            must wait until the update is done.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Table locking causes problems in cases such as when a
-            session is waiting because the disk is full and free space
-            needs to become available before the session can proceed. In
-            this case, all sessions that want to access the problem
-            table are also put in a waiting state until more disk space
-            is made available.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Table locking is also disadvantageous under the following
-        scenario:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            A session issues a <literal role="stmt">SELECT</literal>
-            that takes a long time to run.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Another session then issues an
-            <literal role="stmt">UPDATE</literal> on the same table.
-            This session waits until the
-            <literal role="stmt">SELECT</literal> is finished.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Another session issues another
-            <literal role="stmt">SELECT</literal> statement on the same
-            table. Because <literal role="stmt">UPDATE</literal> has
-            higher priority than <literal role="stmt">SELECT</literal>,
-            this <literal role="stmt">SELECT</literal> waits for the
-            <literal role="stmt">UPDATE</literal> to finish,
-            <emphasis>after</emphasis> waiting for the first
-            <literal role="stmt">SELECT</literal> to finish.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        The following items describe some ways to avoid or reduce
-        contention caused by table locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Try to get the <literal role="stmt">SELECT</literal>
-            statements to run faster so that they lock tables for a
-            shorter time. You might have to create some summary tables
-            to do this.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Start <command>mysqld</command> with
-            <option role="mysqld">--low-priority-updates</option>. For
-            storage engines that use only table-level locking (such as
-            <literal>MyISAM</literal>, <literal>MEMORY</literal>, and
-            <literal>MERGE</literal>), this gives all statements that
-            update (modify) a table lower priority than
-            <literal role="stmt">SELECT</literal> statements. In this
-            case, the second <literal role="stmt">SELECT</literal>
-            statement in the preceding scenario would execute before the
-            <literal role="stmt">UPDATE</literal> statement, and would
-            not need to wait for the first
-            <literal role="stmt">SELECT</literal> to finish.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            To specify that all updates issued in a specific connection
-            should be done with low priority, set the
-            <literal role="sysvar">low_priority_updates</literal> server
-            system variable equal to 1.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            To give a specific <literal role="stmt">INSERT</literal>,
-            <literal role="stmt">UPDATE</literal>, or
-            <literal role="stmt">DELETE</literal> statement lower
-            priority, use the <literal>LOW_PRIORITY</literal> attribute.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            To give a specific <literal role="stmt">SELECT</literal>
-            statement higher priority, use the
-            <literal>HIGH_PRIORITY</literal> attribute. See
-            <xref linkend="select"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Start <command>mysqld</command> with a low value for the
-            <literal role="sysvar">max_write_lock_count</literal> system
-            variable to force MySQL to temporarily elevate the priority
-            of all <literal role="stmt">SELECT</literal> statements that
-            are waiting for a table after a specific number of inserts
-            to the table occur. This permits <literal>READ</literal>
-            locks after a certain number of <literal>WRITE</literal>
-            locks.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you have problems with
-            <literal role="stmt">INSERT</literal> combined with
-            <literal role="stmt">SELECT</literal>, consider switching to
-            <literal>MyISAM</literal> tables, which support concurrent
-            <literal role="stmt">SELECT</literal> and
-            <literal role="stmt">INSERT</literal> statements. (See
-            <xref linkend="concurrent-inserts"/>.)
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you mix inserts and deletes on the same table,
-            <literal role="stmt">INSERT DELAYED</literal> may be of
-            great help. See <xref linkend="insert-delayed"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you have problems with mixed
-            <literal role="stmt">SELECT</literal> and
-            <literal role="stmt">DELETE</literal> statements, the
-            <literal>LIMIT</literal> option to
-            <literal role="stmt">DELETE</literal> may help. See
-            <xref linkend="delete"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Using <literal>SQL_BUFFER_RESULT</literal> with
-            <literal role="stmt">SELECT</literal> statements can help to
-            make the duration of table locks shorter. See
-            <xref linkend="select"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            You could change the locking code in
-            <filename>mysys/thr_lock.c</filename> to use a single queue.
-            In this case, write locks and read locks would have the same
-            priority, which might help some applications.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Here are some tips concerning table locks in MySQL:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Concurrent users are not a problem if you do not mix updates
-            with selects that need to examine many rows in the same
-            table.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            You can use <literal role="stmt">LOCK TABLES</literal> to
-            increase speed, because many updates within a single lock is
-            much faster than updating without locks. Splitting table
-            contents into separate tables may also help.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you encounter speed problems with table locks in MySQL,
-            you may be able to improve performance by converting some of
-            your tables to <literal>InnoDB</literal> or
-            <literal>BDB</literal> tables. See <xref linkend="innodb"/>,
-            and <xref linkend="bdb-storage-engine"/>.
-          </para>
-
-          <formalpara role="mnmas">
-
-            <title>MySQL Enterprise</title>
-
-            <para>
-              Lock contention can seriously degrade performance. The
-              MySQL Enterprise Monitor provides expert advice on
-              avoiding this problem. To subscribe, see
-              &base-url-enterprise;advisors.html.
-            </para>
-
-          </formalpara>
-        </listitem>
-
-      </itemizedlist>
-
-    </section>
-
-    <section id="concurrent-inserts">
-
-      <title>Concurrent Inserts</title>
-
-      <indexterm>
-        <primary>concurrent inserts</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>inserts</primary>
-        <secondary>concurrent</secondary>
-      </indexterm>
-
-      <para>
-        The <literal>MyISAM</literal> storage engine supports concurrent
-        inserts to reduce contention between readers and writers for a
-        given table: If a <literal>MyISAM</literal> table has no holes
-        in the data file (deleted rows in the middle), an
-        <literal role="stmt">INSERT</literal> statement can be executed
-        to add rows to the end of the table at the same time that
-        <literal role="stmt">SELECT</literal> statements are reading
-        rows from the table. If there are multiple
-        <literal role="stmt">INSERT</literal> statements, they are
-        queued and performed in sequence, concurrently with the
-        <literal role="stmt">SELECT</literal> statements. The results of
-        a concurrent <literal role="stmt">INSERT</literal> may not be
-        visible immediately.
-      </para>
-
-      <para>
-        The <literal role="sysvar">concurrent_insert</literal> system
-        variable can be set to modify the concurrent-insert processing.
-        By default, the variable is set to 1 and concurrent inserts are
-        handled as just described. If
-        <literal role="sysvar">concurrent_insert</literal> is set to 0,
-        concurrent inserts are disabled. If the variable is set to 2,
-        concurrent inserts at the end of the table are allowed even for
-        tables that have deleted rows. See also the description of the
-        <link linkend="sysvar_concurrent_insert"><literal role="sysvar">concurrent_insert</literal></link>
-        system variable.
-      </para>
-
-      <para>
-        Under circumstances where concurrent inserts can be used, there
-        is seldom any need to use the <literal>DELAYED</literal>
-        modifier for <literal role="stmt">INSERT</literal> statements.
-        See <xref linkend="insert-delayed"/>.
-      </para>
-
-      <para>
-        If you are using the binary log, concurrent inserts are
-        converted to normal inserts for <literal>CREATE ...
-        SELECT</literal> or
-        <literal role="stmt" condition="insert-select">INSERT ...
-        SELECT</literal> statements. This is done to ensure that you can
-        re-create an exact copy of your tables by applying the log
-        during a backup operation. See <xref linkend="binary-log"/>. In
-        addition, for those statements a read lock is placed on the
-        selected-from table such that inserts into that table are
-        blocked. The effect is that concurrent inserts for that table
-        must wait as well.
-      </para>
-
-      <para>
-        With <literal role="stmt" condition="load-data">LOAD DATA
-        INFILE</literal>, if you specify <literal>CONCURRENT</literal>
-        with a <literal>MyISAM</literal> table that satisfies the
-        condition for concurrent inserts (that is, it contains no free
-        blocks in the middle), other sessions can retrieve data from the
-        table while <literal role="stmt">LOAD DATA</literal> is
-        executing. Use of the <literal>CONCURRENT</literal> option
-        affects the performance of <literal role="stmt">LOAD
-        DATA</literal> a bit, even if no other session is using the
-        table at the same time.
-      </para>
-
-      <para>
-        If you specify <literal>HIGH_PRIORITY</literal>, it overrides
-        the effect of the
-        <option role="mysqld">--low-priority-updates</option> option if
-        the server was started with that option. It also causes
-        concurrent inserts not to be used.
-      </para>
-
-      <para>
-        For <literal role="stmt" condition="lock-tables">LOCK
-        TABLE</literal>, the difference between <literal>READ
-        LOCAL</literal> and <literal>READ</literal> is that
-        <literal>READ LOCAL</literal> permits nonconflicting
-        <literal role="stmt">INSERT</literal> statements (concurrent
-        inserts) to execute while the lock is held. However, this cannot
-        be used if you are going to manipulate the database using
-        processes external to the server while you hold the lock.
-      </para>
-
-    </section>
-
-    <section id="external-locking">
-
-      <title>External Locking</title>
-
-      <indexterm>
-        <primary>external locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>external</secondary>
-      </indexterm>
-
-      <para>
-        External locking is the use of file system locking to manage
-        contention for database tables by multiple processes. External
-        locking is used in situations where a single process such as the
-        MySQL server cannot be assumed to be the only process that
-        requires access to tables. Here are some examples:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            If you run multiple servers that use the same database
-            directory (not recommended), each server must have external
-            locking enabled.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you use <command>myisamchk</command> to perform table
-            maintenance operations on <literal>MyISAM</literal> tables,
-            you must either ensure that the server is not running, or
-            that the server has external locking enabled so that it
-            locks table files as necessary to coordinate with
-            <command>myisamchk</command> for access to the tables. The
-            same is true for use of <command>myisampack</command> to
-            pack <literal>MyISAM</literal> tables.
-          </para>
-
-          <para>
-            If the server is run with external locking enabled, you can
-            use <command>myisamchk</command> at any time for read
-            operations such a checking tables. In this case, if the
-            server tries to update a table that
-            <command>myisamchk</command> is using, the server will wait
-            for <command>myisamchk</command> to finish before it
-            continues.
-          </para>
-
-          <para>
-            If you use <command>myisamchk</command> for write operations
-            such as repairing or optimizing tables, or if you use
-            <command>myisampack</command> to pack tables, you
-            <emphasis>must</emphasis> always ensure that the
-            <command>mysqld</command> server is not using the table. If
-            you don't stop <command>mysqld</command>, you should at
-            least do a <command>mysqladmin flush-tables</command> before
-            you run <command>myisamchk</command>. Your tables
-            <emphasis>may become corrupted</emphasis> if the server and
-            <command>myisamchk</command> access the tables
-            simultaneously.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        With external locking in effect, each process that requires
-        access to a table acquires a file system lock for the table
-        files before proceeding to access the table. If all necessary
-        locks cannot be acquired, the process is blocked from accessing
-        the table until the locks can be obtained (after the process
-        that currently holds the locks releases them).
-      </para>
-
-      <para>
-        External locking affects server performance because the server
-        must sometimes wait for other processes before it can access
-        tables.
-      </para>
-
-      <para>
-        External locking is unnecessary if you run a single server to
-        access a given data directory (which is the usual case) and if
-        no other programs such as <command>myisamchk</command> need to
-        modify tables while the server is running. If you only
-        <emphasis>read</emphasis> tables with other programs, external
-        locking is not required, although <command>myisamchk</command>
-        might report warnings if the server changes tables while
-        <command>myisamchk</command> is reading them.
-      </para>
-
-      <para>
-        With external locking disabled, to use
-        <command>myisamchk</command>, you must either stop the server
-        while <command>myisamchk</command> executes or else lock and
-        flush the tables before running <command>myisamchk</command>.
-        (See <xref linkend="system-optimization"/>.) To avoid this
-        requirement, use the <literal role="stmt">CHECK TABLE</literal>
-        and <literal role="stmt">REPAIR TABLE</literal> statements to
-        check and repair <literal>MyISAM</literal> tables.
-      </para>
-
-      <para>
-        For <command>mysqld</command>, external locking is controlled by
-        the value of the
-        <literal role="sysvar">skip_external_locking</literal> system
-        variable. When this variable is enabled, external locking is
-        disabled, and vice versa. From MySQL 4.0 on, external locking is
-        disabled by default. Before MySQL 4.0, external locking is
-        enabled by default on Linux or when MySQL is configured to use
-        MIT-pthreads.
-      </para>
-
-      <para>
-        Use of external locking can be controlled at server startup by
-        using the <option role="mysqld">--external-locking</option> or
-        <option role="mysqld">--skip-external-locking</option> option.
-      </para>
-
-      <para>
-        If you do use external locking option to enable updates to
-        <literal>MyISAM</literal> tables from many MySQL processes, you
-        must ensure that the following conditions are satisfied:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            You should not use the query cache for queries that use
-            tables that are updated by another process.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            You should not start the server with the
-            <option role="mysqld">--delay-key-write=ALL</option> option
-            or use the <literal>DELAY_KEY_WRITE=1</literal> table option
-            for any shared tables. Otherwise, index corruption can
-            occur.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        The easiest way to satisfy these conditions is to always use
-        <option role="mysqld">--external-locking</option> together with
-        <option role="mysqld">--delay-key-write=OFF</option> and
-        <option role="sysvar">--query-cache-size=0</option>. (This is
-        not done by default because in many setups it is useful to have
-        a mixture of the preceding options.)
-      </para>
-
-    </section>
-
-  </section>
-
-  <section id="optimizing-database-structure">
-
-    <title>Optimizing Database Structure</title>
-
-    <section id="data-size">
-
-      <title>Make Your Data as Small as Possible</title>
-
-      <indexterm>
-        <primary>data</primary>
-        <secondary>size</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>reducing</primary>
-        <secondary>data size</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>storage space</primary>
-        <secondary>minimizing</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>tables</primary>
-        <secondary>improving performance</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>performance</primary>
-        <secondary>improving</secondary>
-      </indexterm>
-
-      <para>
-        One of the most basic optimizations is to design your tables to
-        take as little space on the disk as possible. This can result in
-        huge improvements because disk reads are faster, and smaller
-        tables normally require less main memory while their contents
-        are being actively processed during query execution. Indexing
-        also is a lesser resource burden if done on smaller columns.
-      </para>
-
-      <para>
-        MySQL supports many different storage engines (table types) and
-        row formats. For each table, you can decide which storage and
-        indexing method to use. Choosing the proper table format for
-        your application may give you a big performance gain. See
-        <xref linkend="storage-engines"/>.
-      </para>
-
-      <para>
-        You can get better performance for a table and minimize storage
-        space by using the techniques listed here:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Use the most efficient (smallest) data types possible. MySQL
-            has many specialized types that save disk space and memory.
-            For example, use the smaller integer types if possible to
-            get smaller tables. <literal role="type">MEDIUMINT</literal>
-            is often a better choice than
-            <literal role="type">INT</literal> because a
-            <literal role="type">MEDIUMINT</literal> column uses 25%
-            less space.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Declare columns to be <literal>NOT NULL</literal> if
-            possible. It makes everything faster and you save one bit
-            per column. If you really need <literal>NULL</literal> in
-            your application, you should definitely use it. Just avoid
-            having it on all columns by default.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            For <literal>MyISAM</literal> tables, if you do not have any
-            variable-length columns
-            (<literal role="type">VARCHAR</literal>,
-            <literal role="type">TEXT</literal>, or
-            <literal role="type">BLOB</literal> columns), a fixed-size
-            row format is used. This is faster but unfortunately may
-            waste some space. See
-            <xref linkend="myisam-table-formats"/>. You can hint that
-            you want to have fixed length rows even if you have
-            <literal role="type">VARCHAR</literal> columns with the
-            <literal role="stmt">CREATE TABLE</literal> option
-            <literal>ROW_FORMAT=FIXED</literal>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Starting with MySQL 5.0.3, <literal>InnoDB</literal> tables
-            use a more compact storage format. In earlier versions of
-            MySQL, <literal>InnoDB</literal> rows contain some redundant
-            information, such as the number of columns and the length of
-            each column, even for fixed-size columns. By default, tables
-            are created in the compact format
-            (<literal>ROW_FORMAT=COMPACT</literal>). If you wish to
-            downgrade to older versions of MySQL, you can request the
-            old format with <literal>ROW_FORMAT=REDUNDANT</literal>.
-          </para>
-
-          <para>
-            The presence of the compact row format decreases row storage
-            space by about 20% at the cost of increasing CPU use for
-            some operations. If your workload is a typical one that is
-            limited by cache hit rates and disk speed it is likely to be
-            faster. If it is a rare case that is limited by CPU speed,
-            it might be slower.
-          </para>
-
-          <para>
-            The compact <literal>InnoDB</literal> format also changes
-            how <literal role="type">CHAR</literal> columns containing
-            UTF-8 data are stored. With
-            <literal>ROW_FORMAT=REDUNDANT</literal>, a UTF-8
-            <literal>CHAR(<replaceable>N</replaceable>)</literal>
-            occupies 3 &times; <replaceable>N</replaceable> bytes, given
-            that the maximum length of a UTF-8 encoded character is
-            three bytes. Many languages can be written primarily using
-            single-byte UTF-8 characters, so a fixed storage length
-            often wastes space. With
-            <literal>ROW_FORMAT=COMPACT</literal> format,
-            <literal>InnoDB</literal> allocates a variable amount of
-            storage in the range from <replaceable>N</replaceable> to 3
-            &times; <replaceable>N</replaceable> bytes for these columns
-            by stripping trailing spaces if necessary. The minimum
-            storage length is kept as <replaceable>N</replaceable> bytes
-            to facilitate in-place updates in typical cases.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            The primary index of a table should be as short as possible.
-            This makes identification of each row easy and efficient.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Create only the indexes that you really need. Indexes are
-            good for retrieval but bad when you need to store data
-            quickly. If you access a table mostly by searching on a
-            combination of columns, create an index on them. The first
-            part of the index should be the column most used. If you
-            <emphasis>always</emphasis> use many columns when selecting
-            from the table, the first column in the index should be the
-            one with the most duplicates to obtain better compression of
-            the index.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If it is very likely that a string column has a unique
-            prefix on the first number of characters, it is better to
-            index only this prefix, using MySQL's support for creating
-            an index on the leftmost part of the column (see
-            <xref linkend="create-index"/>). Shorter indexes are faster,
-            not only because they require less disk space, but because
-            they also give you more hits in the index cache, and thus
-            fewer disk seeks. See <xref linkend="server-parameters"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            In some circumstances, it can be beneficial to split into
-            two a table that is scanned very often. This is especially
-            true if it is a dynamic-format table and it is possible to
-            use a smaller static format table that can be used to find
-            the relevant rows when scanning the table.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-    </section>
-
-    <section id="indexes">
-
       <title>Column Indexes</title>
 
       <indexterm>

@@ -8882,7 +7745,7 @@
         MySQL can create composite indexes (that is, indexes on multiple
         columns). An index may consist of up to 16 columns. For certain
         data types, you can index a prefix of the column (see
-        <xref linkend="indexes"/>).
+        <xref linkend="column-indexes"/>).
       </para>
 
       <para>

@@ -10393,6 +9256,1149 @@
 
     </section>
 
+  </section>
+
+  <section id="locking-issues">
+
+    <title>Locking Issues</title>
+
+    <para>
+      MySQL manages contention for table contents using locking:
+    </para>
+
+    <itemizedlist>
+
+      <listitem>
+        <para>
+          Internal locking is performed within the MySQL server itself
+          to manage contention for table contents by multiple threads.
+          This type of locking is internal because it is performed
+          entirely by the server and involves no other programs. See
+          <xref linkend="internal-locking"/>.
+        </para>
+      </listitem>
+
+      <listitem>
+        <para>
+          External locking occurs when the server and other programs
+          lock table files to coordinate among themselves which program
+          can access the tables at which time. See
+          <xref linkend="external-locking"/>.
+        </para>
+      </listitem>
+
+    </itemizedlist>
+
+    <section id="internal-locking">
+
+      <title>Internal Locking Methods</title>
+
+      <indexterm>
+        <primary>internal locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>internal</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking methods</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>methods</primary>
+        <secondary>locking</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>row-level locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>page-level locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>table-level locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>row-level</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>page-level</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>table-level</secondary>
+      </indexterm>
+
+      <para>
+        This section discusses internal locking; that is, locking
+        performed within the MySQL server itself to manage contention
+        for table contents by multiple sessions. This type of locking is
+        internal because it is performed entirely by the server and
+        involves no other programs. External locking occurs when the
+        server and other programs lock table files to coordinate among
+        themselves which program can access the tables at which time.
+        See <xref linkend="external-locking"/>.
+      </para>
+
+      <para>
+        MySQL uses table-level locking for <literal>MyISAM</literal>,
+        <literal>MEMORY</literal> and <literal>MERGE</literal> tables,
+        page-level locking for <literal>BDB</literal> tables, and
+        row-level locking for <literal>InnoDB</literal> tables.
+      </para>
+
+      <para>
+        In many cases, you can make an educated guess about which
+        locking type is best for an application, but generally it is
+        difficult to say that a given lock type is better than another.
+        Everything depends on the application and different parts of an
+        application may require different lock types.
+      </para>
+
+      <para>
+        To decide whether you want to use a storage engine with
+        row-level locking, you should look at what your application does
+        and what mix of select and update statements it uses. For
+        example, most Web applications perform many selects, relatively
+        few deletes, updates based mainly on key values, and inserts
+        into a few specific tables. The base MySQL
+        <literal>MyISAM</literal> setup is very well tuned for this.
+      </para>
+
+      <formalpara role="mnmas">
+
+        <title>MySQL Enterprise</title>
+
+        <para>
+          The MySQL Enterprise Monitor provides expert advice on when to
+          use table-level locking and when to use row-level locking. To
+          subscribe, see &base-url-enterprise;advisors.html.
+        </para>
+
+      </formalpara>
+
+      <para>
+        Table locking in MySQL is deadlock-free for storage engines that
+        use table-level locking. Deadlock avoidance is managed by always
+        requesting all needed locks at once at the beginning of a query
+        and always locking the tables in the same order.
+      </para>
+
+      <para>
+        MySQL grants table write locks as follows:
+      </para>
+
+      <orderedlist>
+
+        <listitem>
+          <para>
+            If there are no locks on the table, put a write lock on it.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Otherwise, put the lock request in the write lock queue.
+          </para>
+        </listitem>
+
+      </orderedlist>
+
+      <para>
+        MySQL grants table read locks as follows:
+      </para>
+
+      <orderedlist>
+
+        <listitem>
+          <para>
+            If there are no write locks on the table, put a read lock on
+            it.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Otherwise, put the lock request in the read lock queue.
+          </para>
+        </listitem>
+
+      </orderedlist>
+
+      <para>
+        Table updates are given higher priority than table retrievals.
+        Therefore, when a lock is released, the lock is made available
+        to the requests in the write lock queue and then to the requests
+        in the read lock queue. This ensures that updates to a table are
+        not <quote>starved</quote> even if there is heavy
+        <literal role="stmt">SELECT</literal> activity for the table.
+        However, if you have many updates for a table,
+        <literal role="stmt">SELECT</literal> statements wait until
+        there are no more updates.
+      </para>
+
+      <para>
+        For information on altering the priority of reads and writes,
+        see <xref linkend="table-locking"/>.
+      </para>
+
+      <para>
+        You can analyze the table lock contention on your system by
+        checking the
+        <literal role="statvar">Table_locks_immediate</literal> and
+        <literal role="statvar">Table_locks_waited</literal> status
+        variables, which indicate the number of times that requests for
+        table locks could be granted immediately and the number that had
+        to wait, respectively:
+      </para>
+
+<programlisting>
+mysql&gt; <userinput>SHOW STATUS LIKE 'Table%';</userinput>
++-----------------------+---------+
+| Variable_name         | Value   |
++-----------------------+---------+
+| Table_locks_immediate | 1151552 |
+| Table_locks_waited    | 15324   |
++-----------------------+---------+
+</programlisting>
+
+      <indexterm>
+        <primary>concurrent inserts</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>inserts</primary>
+        <secondary>concurrent</secondary>
+      </indexterm>
+
+      <para>
+        The <literal>MyISAM</literal> storage engine supports concurrent
+        inserts to reduce contention between readers and writers for a
+        given table: If a <literal>MyISAM</literal> table has no free
+        blocks in the middle of the data file, rows are always inserted
+        at the end of the data file. In this case, you can freely mix
+        concurrent <literal role="stmt">INSERT</literal> and
+        <literal role="stmt">SELECT</literal> statements for a
+        <literal>MyISAM</literal> table without locks. That is, you can
+        insert rows into a <literal>MyISAM</literal> table at the same
+        time other clients are reading from it. Holes can result from
+        rows having been deleted from or updated in the middle of the
+        table. If there are holes, concurrent inserts are disabled but
+        are enabled again automatically when all holes have been filled
+        with new data. This behavior is altered by the
+        <literal role="sysvar">concurrent_insert</literal> system
+        variable. See <xref linkend="concurrent-inserts"/>.
+      </para>
+
+      <para>
+        If you acquire a table lock explicitly with
+        <literal role="stmt">LOCK TABLES</literal>, you can request a
+        <literal>READ LOCAL</literal> lock rather than a
+        <literal>READ</literal> lock to enable other sessions to perform
+        concurrent inserts while you have the table locked.
+      </para>
+
+      <para>
+        To perform many <literal role="stmt">INSERT</literal> and
+        <literal role="stmt">SELECT</literal> operations on a table
+        <literal>real_table</literal> when concurrent inserts are not
+        possible, you can insert rows into a temporary table
+        <literal>temp_table</literal> and update the real table with the
+        rows from the temporary table periodically. This can be done
+        with the following code:
+      </para>
+
+<programlisting>
+mysql&gt; <userinput>LOCK TABLES real_table WRITE, temp_table WRITE;</userinput>
+mysql&gt; <userinput>INSERT INTO real_table SELECT * FROM temp_table;</userinput>
+mysql&gt; <userinput>DELETE FROM temp_table;</userinput>
+mysql&gt; <userinput>UNLOCK TABLES;</userinput>
+</programlisting>
+
+      <para>
+        <literal>InnoDB</literal> uses row locks and
+        <literal>BDB</literal> uses page locks. Deadlocks are possible
+        for these storage engines because they automatically acquire
+        locks during the processing of SQL statements, not at the start
+        of the transaction.
+      </para>
+
+      <para>
+        Advantages of row-level locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Fewer lock conflicts when different sessions access
+            different rows
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Fewer changes for rollbacks
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Possible to lock a single row for a long time
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Disadvantages of row-level locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Requires more memory than page-level or table-level locks
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Slower than page-level or table-level locks when used on a
+            large part of the table because you must acquire many more
+            locks
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Slower than other locks if you often do <literal>GROUP
+            BY</literal> operations on a large part of the data or if
+            you must scan the entire table frequently
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Generally, table locks are superior to page-level or row-level
+        locks in the following cases:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Most statements for the table are reads
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Statements for the table are a mix of reads and writes,
+            where writes are updates or deletes for a single row that
+            can be fetched with one key read:
+          </para>
+
+<programlisting>
+UPDATE <replaceable>tbl_name</replaceable> SET <replaceable>column</replaceable>=<replaceable>value</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
+DELETE FROM <replaceable>tbl_name</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
+</programlisting>
+        </listitem>
+
+        <listitem>
+          <para>
+            <literal role="stmt">SELECT</literal> combined with
+            concurrent <literal role="stmt">INSERT</literal> statements,
+            and very few <literal role="stmt">UPDATE</literal> or
+            <literal role="stmt">DELETE</literal> statements
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Many scans or <literal>GROUP BY</literal> operations on the
+            entire table without any writers
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        With higher-level locks, you can more easily tune applications
+        by supporting locks of different types, because the lock
+        overhead is less than for row-level locks.
+      </para>
+
+      <para>
+        Options other than row-level or page-level locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Versioning (such as that used in MySQL for concurrent
+            inserts) where it is possible to have one writer at the same
+            time as many readers. This means that the database or table
+            supports different views for the data depending on when
+            access begins. Other common terms for this are <quote>time
+            travel,</quote> <quote>copy on write,</quote> or <quote>copy
+            on demand.</quote>
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Copy on demand is in many cases superior to page-level or
+            row-level locking. However, in the worst case, it can use
+            much more memory than using normal locks.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Instead of using row-level locks, you can employ
+            application-level locks, such as those provided by
+            <literal role="func">GET_LOCK()</literal> and
+            <literal role="func">RELEASE_LOCK()</literal> in MySQL.
+            These are advisory locks, so they work only with
+            applications that cooperate with each other. See
+            <xref linkend="miscellaneous-functions"/>.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+    </section>
+
+    <section id="table-locking">
+
+      <title>Table Locking Issues</title>
+
+      <indexterm>
+        <primary>problems</primary>
+        <secondary>table locking</secondary>
+      </indexterm>
+
+      <para>
+        To achieve a very high lock speed, MySQL uses table locking
+        (instead of page, row, or column locking) for all storage
+        engines except <literal>InnoDB</literal>,
+        <literal>BDB</literal>, and
+        <literal role="se">NDBCLUSTER</literal>.
+      </para>
+
+      <para>
+        For <literal>InnoDB</literal> and <literal>BDB</literal> tables,
+        MySQL uses table locking only if you explicitly lock the table
+        with <literal role="stmt">LOCK TABLES</literal>. For these
+        storage engines, avoid using <literal role="stmt">LOCK
+        TABLES</literal> at all, because <literal>InnoDB</literal> uses
+        automatic row-level locking and <literal>BDB</literal> uses
+        page-level locking to ensure transaction isolation.
+      </para>
+
+      <para>
+        For large tables, table locking is often better than row
+        locking, but there are some disadvantages:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Table locking enables many sessions to read from a table at
+            the same time, but if a session wants to write to a table,
+            it must first get exclusive access. During the update, all
+            other sessions that want to access this particular table
+            must wait until the update is done.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Table locking causes problems in cases such as when a
+            session is waiting because the disk is full and free space
+            needs to become available before the session can proceed. In
+            this case, all sessions that want to access the problem
+            table are also put in a waiting state until more disk space
+            is made available.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Table locking is also disadvantageous under the following
+        scenario:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            A session issues a <literal role="stmt">SELECT</literal>
+            that takes a long time to run.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Another session then issues an
+            <literal role="stmt">UPDATE</literal> on the same table.
+            This session waits until the
+            <literal role="stmt">SELECT</literal> is finished.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Another session issues another
+            <literal role="stmt">SELECT</literal> statement on the same
+            table. Because <literal role="stmt">UPDATE</literal> has
+            higher priority than <literal role="stmt">SELECT</literal>,
+            this <literal role="stmt">SELECT</literal> waits for the
+            <literal role="stmt">UPDATE</literal> to finish,
+            <emphasis>after</emphasis> waiting for the first
+            <literal role="stmt">SELECT</literal> to finish.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        The following items describe some ways to avoid or reduce
+        contention caused by table locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Try to get the <literal role="stmt">SELECT</literal>
+            statements to run faster so that they lock tables for a
+            shorter time. You might have to create some summary tables
+            to do this.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Start <command>mysqld</command> with
+            <option role="mysqld">--low-priority-updates</option>. For
+            storage engines that use only table-level locking (such as
+            <literal>MyISAM</literal>, <literal>MEMORY</literal>, and
+            <literal>MERGE</literal>), this gives all statements that
+            update (modify) a table lower priority than
+            <literal role="stmt">SELECT</literal> statements. In this
+            case, the second <literal role="stmt">SELECT</literal>
+            statement in the preceding scenario would execute before the
+            <literal role="stmt">UPDATE</literal> statement, and would
+            not need to wait for the first
+            <literal role="stmt">SELECT</literal> to finish.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            To specify that all updates issued in a specific connection
+            should be done with low priority, set the
+            <literal role="sysvar">low_priority_updates</literal> server
+            system variable equal to 1.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            To give a specific <literal role="stmt">INSERT</literal>,
+            <literal role="stmt">UPDATE</literal>, or
+            <literal role="stmt">DELETE</literal> statement lower
+            priority, use the <literal>LOW_PRIORITY</literal> attribute.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            To give a specific <literal role="stmt">SELECT</literal>
+            statement higher priority, use the
+            <literal>HIGH_PRIORITY</literal> attribute. See
+            <xref linkend="select"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Start <command>mysqld</command> with a low value for the
+            <literal role="sysvar">max_write_lock_count</literal> system
+            variable to force MySQL to temporarily elevate the priority
+            of all <literal role="stmt">SELECT</literal> statements that
+            are waiting for a table after a specific number of inserts
+            to the table occur. This permits <literal>READ</literal>
+            locks after a certain number of <literal>WRITE</literal>
+            locks.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you have problems with
+            <literal role="stmt">INSERT</literal> combined with
+            <literal role="stmt">SELECT</literal>, consider switching to
+            <literal>MyISAM</literal> tables, which support concurrent
+            <literal role="stmt">SELECT</literal> and
+            <literal role="stmt">INSERT</literal> statements. (See
+            <xref linkend="concurrent-inserts"/>.)
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you mix inserts and deletes on the same table,
+            <literal role="stmt">INSERT DELAYED</literal> may be of
+            great help. See <xref linkend="insert-delayed"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you have problems with mixed
+            <literal role="stmt">SELECT</literal> and
+            <literal role="stmt">DELETE</literal> statements, the
+            <literal>LIMIT</literal> option to
+            <literal role="stmt">DELETE</literal> may help. See
+            <xref linkend="delete"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Using <literal>SQL_BUFFER_RESULT</literal> with
+            <literal role="stmt">SELECT</literal> statements can help to
+            make the duration of table locks shorter. See
+            <xref linkend="select"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            You could change the locking code in
+            <filename>mysys/thr_lock.c</filename> to use a single queue.
+            In this case, write locks and read locks would have the same
+            priority, which might help some applications.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Here are some tips concerning table locks in MySQL:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Concurrent users are not a problem if you do not mix updates
+            with selects that need to examine many rows in the same
+            table.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            You can use <literal role="stmt">LOCK TABLES</literal> to
+            increase speed, because many updates within a single lock is
+            much faster than updating without locks. Splitting table
+            contents into separate tables may also help.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you encounter speed problems with table locks in MySQL,
+            you may be able to improve performance by converting some of
+            your tables to <literal>InnoDB</literal> or
+            <literal>BDB</literal> tables. See <xref linkend="innodb"/>,
+            and <xref linkend="bdb-storage-engine"/>.
+          </para>
+
+          <formalpara role="mnmas">
+
+            <title>MySQL Enterprise</title>
+
+            <para>
+              Lock contention can seriously degrade performance. The
+              MySQL Enterprise Monitor provides expert advice on
+              avoiding this problem. To subscribe, see
+              &base-url-enterprise;advisors.html.
+            </para>
+
+          </formalpara>
+        </listitem>
+
+      </itemizedlist>
+
+    </section>
+
+    <section id="concurrent-inserts">
+
+      <title>Concurrent Inserts</title>
+
+      <indexterm>
+        <primary>concurrent inserts</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>inserts</primary>
+        <secondary>concurrent</secondary>
+      </indexterm>
+
+      <para>
+        The <literal>MyISAM</literal> storage engine supports concurrent
+        inserts to reduce contention between readers and writers for a
+        given table: If a <literal>MyISAM</literal> table has no holes
+        in the data file (deleted rows in the middle), an
+        <literal role="stmt">INSERT</literal> statement can be executed
+        to add rows to the end of the table at the same time that
+        <literal role="stmt">SELECT</literal> statements are reading
+        rows from the table. If there are multiple
+        <literal role="stmt">INSERT</literal> statements, they are
+        queued and performed in sequence, concurrently with the
+        <literal role="stmt">SELECT</literal> statements. The results of
+        a concurrent <literal role="stmt">INSERT</literal> may not be
+        visible immediately.
+      </para>
+
+      <para>
+        The <literal role="sysvar">concurrent_insert</literal> system
+        variable can be set to modify the concurrent-insert processing.
+        By default, the variable is set to 1 and concurrent inserts are
+        handled as just described. If
+        <literal role="sysvar">concurrent_insert</literal> is set to 0,
+        concurrent inserts are disabled. If the variable is set to 2,
+        concurrent inserts at the end of the table are allowed even for
+        tables that have deleted rows. See also the description of the
+        <link linkend="sysvar_concurrent_insert"><literal role="sysvar">concurrent_insert</literal></link>
+        system variable.
+      </para>
+
+      <para>
+        Under circumstances where concurrent inserts can be used, there
+        is seldom any need to use the <literal>DELAYED</literal>
+        modifier for <literal role="stmt">INSERT</literal> statements.
+        See <xref linkend="insert-delayed"/>.
+      </para>
+
+      <para>
+        If you are using the binary log, concurrent inserts are
+        converted to normal inserts for <literal>CREATE ...
+        SELECT</literal> or
+        <literal role="stmt" condition="insert-select">INSERT ...
+        SELECT</literal> statements. This is done to ensure that you can
+        re-create an exact copy of your tables by applying the log
+        during a backup operation. See <xref linkend="binary-log"/>. In
+        addition, for those statements a read lock is placed on the
+        selected-from table such that inserts into that table are
+        blocked. The effect is that concurrent inserts for that table
+        must wait as well.
+      </para>
+
+      <para>
+        With <literal role="stmt" condition="load-data">LOAD DATA
+        INFILE</literal>, if you specify <literal>CONCURRENT</literal>
+        with a <literal>MyISAM</literal> table that satisfies the
+        condition for concurrent inserts (that is, it contains no free
+        blocks in the middle), other sessions can retrieve data from the
+        table while <literal role="stmt">LOAD DATA</literal> is
+        executing. Use of the <literal>CONCURRENT</literal> option
+        affects the performance of <literal role="stmt">LOAD
+        DATA</literal> a bit, even if no other session is using the
+        table at the same time.
+      </para>
+
+      <para>
+        If you specify <literal>HIGH_PRIORITY</literal>, it overrides
+        the effect of the
+        <option role="mysqld">--low-priority-updates</option> option if
+        the server was started with that option. It also causes
+        concurrent inserts not to be used.
+      </para>
+
+      <para>
+        For <literal role="stmt" condition="lock-tables">LOCK
+        TABLE</literal>, the difference between <literal>READ
+        LOCAL</literal> and <literal>READ</literal> is that
+        <literal>READ LOCAL</literal> permits nonconflicting
+        <literal role="stmt">INSERT</literal> statements (concurrent
+        inserts) to execute while the lock is held. However, this cannot
+        be used if you are going to manipulate the database using
+        processes external to the server while you hold the lock.
+      </para>
+
+    </section>
+
+    <section id="external-locking">
+
+      <title>External Locking</title>
+
+      <indexterm>
+        <primary>external locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>external</secondary>
+      </indexterm>
+
+      <para>
+        External locking is the use of file system locking to manage
+        contention for database tables by multiple processes. External
+        locking is used in situations where a single process such as the
+        MySQL server cannot be assumed to be the only process that
+        requires access to tables. Here are some examples:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            If you run multiple servers that use the same database
+            directory (not recommended), each server must have external
+            locking enabled.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you use <command>myisamchk</command> to perform table
+            maintenance operations on <literal>MyISAM</literal> tables,
+            you must either ensure that the server is not running, or
+            that the server has external locking enabled so that it
+            locks table files as necessary to coordinate with
+            <command>myisamchk</command> for access to the tables. The
+            same is true for use of <command>myisampack</command> to
+            pack <literal>MyISAM</literal> tables.
+          </para>
+
+          <para>
+            If the server is run with external locking enabled, you can
+            use <command>myisamchk</command> at any time for read
+            operations such a checking tables. In this case, if the
+            server tries to update a table that
+            <command>myisamchk</command> is using, the server will wait
+            for <command>myisamchk</command> to finish before it
+            continues.
+          </para>
+
+          <para>
+            If you use <command>myisamchk</command> for write operations
+            such as repairing or optimizing tables, or if you use
+            <command>myisampack</command> to pack tables, you
+            <emphasis>must</emphasis> always ensure that the
+            <command>mysqld</command> server is not using the table. If
+            you don't stop <command>mysqld</command>, you should at
+            least do a <command>mysqladmin flush-tables</command> before
+            you run <command>myisamchk</command>. Your tables
+            <emphasis>may become corrupted</emphasis> if the server and
+            <command>myisamchk</command> access the tables
+            simultaneously.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        With external locking in effect, each process that requires
+        access to a table acquires a file system lock for the table
+        files before proceeding to access the table. If all necessary
+        locks cannot be acquired, the process is blocked from accessing
+        the table until the locks can be obtained (after the process
+        that currently holds the locks releases them).
+      </para>
+
+      <para>
+        External locking affects server performance because the server
+        must sometimes wait for other processes before it can access
+        tables.
+      </para>
+
+      <para>
+        External locking is unnecessary if you run a single server to
+        access a given data directory (which is the usual case) and if
+        no other programs such as <command>myisamchk</command> need to
+        modify tables while the server is running. If you only
+        <emphasis>read</emphasis> tables with other programs, external
+        locking is not required, although <command>myisamchk</command>
+        might report warnings if the server changes tables while
+        <command>myisamchk</command> is reading them.
+      </para>
+
+      <para>
+        With external locking disabled, to use
+        <command>myisamchk</command>, you must either stop the server
+        while <command>myisamchk</command> executes or else lock and
+        flush the tables before running <command>myisamchk</command>.
+        (See <xref linkend="system-optimization"/>.) To avoid this
+        requirement, use the <literal role="stmt">CHECK TABLE</literal>
+        and <literal role="stmt">REPAIR TABLE</literal> statements to
+        check and repair <literal>MyISAM</literal> tables.
+      </para>
+
+      <para>
+        For <command>mysqld</command>, external locking is controlled by
+        the value of the
+        <literal role="sysvar">skip_external_locking</literal> system
+        variable. When this variable is enabled, external locking is
+        disabled, and vice versa. From MySQL 4.0 on, external locking is
+        disabled by default. Before MySQL 4.0, external locking is
+        enabled by default on Linux or when MySQL is configured to use
+        MIT-pthreads.
+      </para>
+
+      <para>
+        Use of external locking can be controlled at server startup by
+        using the <option role="mysqld">--external-locking</option> or
+        <option role="mysqld">--skip-external-locking</option> option.
+      </para>
+
+      <para>
+        If you do use external locking option to enable updates to
+        <literal>MyISAM</literal> tables from many MySQL processes, you
+        must ensure that the following conditions are satisfied:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            You should not use the query cache for queries that use
+            tables that are updated by another process.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            You should not start the server with the
+            <option role="mysqld">--delay-key-write=ALL</option> option
+            or use the <literal>DELAY_KEY_WRITE=1</literal> table option
+            for any shared tables. Otherwise, index corruption can
+            occur.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        The easiest way to satisfy these conditions is to always use
+        <option role="mysqld">--external-locking</option> together with
+        <option role="mysqld">--delay-key-write=OFF</option> and
+        <option role="sysvar">--query-cache-size=0</option>. (This is
+        not done by default because in many setups it is useful to have
+        a mixture of the preceding options.)
+      </para>
+
+    </section>
+
+  </section>
+
+  <section id="optimizing-database-structure">
+
+    <title>Optimizing Database Structure</title>
+
+    <section id="data-size">
+
+      <title>Make Your Data as Small as Possible</title>
+
+      <indexterm>
+        <primary>data</primary>
+        <secondary>size</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>reducing</primary>
+        <secondary>data size</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>storage space</primary>
+        <secondary>minimizing</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>tables</primary>
+        <secondary>improving performance</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>performance</primary>
+        <secondary>improving</secondary>
+      </indexterm>
+
+      <para>
+        One of the most basic optimizations is to design your tables to
+        take as little space on the disk as possible. This can result in
+        huge improvements because disk reads are faster, and smaller
+        tables normally require less main memory while their contents
+        are being actively processed during query execution. Indexing
+        also is a lesser resource burden if done on smaller columns.
+      </para>
+
+      <para>
+        MySQL supports many different storage engines (table types) and
+        row formats. For each table, you can decide which storage and
+        indexing method to use. Choosing the proper table format for
+        your application may give you a big performance gain. See
+        <xref linkend="storage-engines"/>.
+      </para>
+
+      <para>
+        You can get better performance for a table and minimize storage
+        space by using the techniques listed here:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Use the most efficient (smallest) data types possible. MySQL
+            has many specialized types that save disk space and memory.
+            For example, use the smaller integer types if possible to
+            get smaller tables. <literal role="type">MEDIUMINT</literal>
+            is often a better choice than
+            <literal role="type">INT</literal> because a
+            <literal role="type">MEDIUMINT</literal> column uses 25%
+            less space.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Declare columns to be <literal>NOT NULL</literal> if
+            possible. It makes everything faster and you save one bit
+            per column. If you really need <literal>NULL</literal> in
+            your application, you should definitely use it. Just avoid
+            having it on all columns by default.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            For <literal>MyISAM</literal> tables, if you do not have any
+            variable-length columns
+            (<literal role="type">VARCHAR</literal>,
+            <literal role="type">TEXT</literal>, or
+            <literal role="type">BLOB</literal> columns), a fixed-size
+            row format is used. This is faster but unfortunately may
+            waste some space. See
+            <xref linkend="myisam-table-formats"/>. You can hint that
+            you want to have fixed length rows even if you have
+            <literal role="type">VARCHAR</literal> columns with the
+            <literal role="stmt">CREATE TABLE</literal> option
+            <literal>ROW_FORMAT=FIXED</literal>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Starting with MySQL 5.0.3, <literal>InnoDB</literal> tables
+            use a more compact storage format. In earlier versions of
+            MySQL, <literal>InnoDB</literal> rows contain some redundant
+            information, such as the number of columns and the length of
+            each column, even for fixed-size columns. By default, tables
+            are created in the compact format
+            (<literal>ROW_FORMAT=COMPACT</literal>). If you wish to
+            downgrade to older versions of MySQL, you can request the
+            old format with <literal>ROW_FORMAT=REDUNDANT</literal>.
+          </para>
+
+          <para>
+            The presence of the compact row format decreases row storage
+            space by about 20% at the cost of increasing CPU use for
+            some operations. If your workload is a typical one that is
+            limited by cache hit rates and disk speed it is likely to be
+            faster. If it is a rare case that is limited by CPU speed,
+            it might be slower.
+          </para>
+
+          <para>
+            The compact <literal>InnoDB</literal> format also changes
+            how <literal role="type">CHAR</literal> columns containing
+            UTF-8 data are stored. With
+            <literal>ROW_FORMAT=REDUNDANT</literal>, a UTF-8
+            <literal>CHAR(<replaceable>N</replaceable>)</literal>
+            occupies 3 &times; <replaceable>N</replaceable> bytes, given
+            that the maximum length of a UTF-8 encoded character is
+            three bytes. Many languages can be written primarily using
+            single-byte UTF-8 characters, so a fixed storage length
+            often wastes space. With
+            <literal>ROW_FORMAT=COMPACT</literal> format,
+            <literal>InnoDB</literal> allocates a variable amount of
+            storage in the range from <replaceable>N</replaceable> to 3
+            &times; <replaceable>N</replaceable> bytes for these columns
+            by stripping trailing spaces if necessary. The minimum
+            storage length is kept as <replaceable>N</replaceable> bytes
+            to facilitate in-place updates in typical cases.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            The primary index of a table should be as short as possible.
+            This makes identification of each row easy and efficient.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Create only the indexes that you really need. Indexes are
+            good for retrieval but bad when you need to store data
+            quickly. If you access a table mostly by searching on a
+            combination of columns, create an index on them. The first
+            part of the index should be the column most used. If you
+            <emphasis>always</emphasis> use many columns when selecting
+            from the table, the first column in the index should be the
+            one with the most duplicates to obtain better compression of
+            the index.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If it is very likely that a string column has a unique
+            prefix on the first number of characters, it is better to
+            index only this prefix, using MySQL's support for creating
+            an index on the leftmost part of the column (see
+            <xref linkend="create-index"/>). Shorter indexes are faster,
+            not only because they require less disk space, but because
+            they also give you more hits in the index cache, and thus
+            fewer disk seeks. See <xref linkend="server-parameters"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            In some circumstances, it can be beneficial to split into
+            two a table that is scanned very often. This is especially
+            true if it is a dynamic-format table and it is possible to
+            use a smaller static format table that can be used to find
+            the relevant rows when scanning the table.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+    </section>
+
     <section id="table-cache">
 
       <title>How MySQL Opens and Closes Tables</title>


Modified: trunk/refman-5.0/renamed-nodes.txt
===================================================================
--- trunk/refman-5.0/renamed-nodes.txt	2010-07-14 15:11:37 UTC (rev 21727)
+++ trunk/refman-5.0/renamed-nodes.txt	2010-07-14 15:35:58 UTC (rev 21728)
Changed blocks: 1, Lines Added: 1, Lines Deleted: 0; 619 bytes

@@ -42,6 +42,7 @@
 eiffel apis-eiffel 2009-09-01
 german-character-set charset-we-sets 2010-08-08
 group-by-hidden-fields group-by-hidden-columns 2010-01-01
+indexes column-indexes 2011-07-14
 innodb-and-autocommit innodb-transaction-model 2009-11-24
 innodb-consistent-read-example innodb-consistent-read 2010-03-10
 innodb-general-monitor innodb-monitors 2010-11-05


Modified: trunk/refman-5.0/sql-syntax-data-definition.xml
===================================================================
--- trunk/refman-5.0/sql-syntax-data-definition.xml	2010-07-14 15:11:37 UTC (rev 21727)
+++ trunk/refman-5.0/sql-syntax-data-definition.xml	2010-07-14 15:35:58 UTC (rev 21728)
Changed blocks: 1, Lines Added: 1, Lines Deleted: 1; 663 bytes

@@ -3168,7 +3168,7 @@
           <literal role="type">VARBINARY</literal>, and
           <literal role="type">BLOB</literal> columns. Indexing only a
           prefix of column values like this can make the index file much
-          smaller. See <xref linkend="indexes"/>.
+          smaller. See <xref linkend="column-indexes"/>.
         </para>
 
         <indexterm>


Modified: trunk/refman-5.1/data-types.xml
===================================================================
--- trunk/refman-5.1/data-types.xml	2010-07-14 15:11:37 UTC (rev 21727)
+++ trunk/refman-5.1/data-types.xml	2010-07-14 15:35:58 UTC (rev 21728)
Changed blocks: 1, Lines Added: 1, Lines Deleted: 1; 594 bytes

@@ -4648,7 +4648,7 @@
             specify an index prefix length. For
             <literal role="type">CHAR</literal> and
             <literal role="type">VARCHAR</literal>, a prefix length is
-            optional. See <xref linkend="indexes"/>.
+            optional. See <xref linkend="column-indexes"/>.
           </para>
         </listitem>
 


Modified: trunk/refman-5.1/optimization.xml
===================================================================
--- trunk/refman-5.1/optimization.xml	2010-07-14 15:11:37 UTC (rev 21727)
+++ trunk/refman-5.1/optimization.xml	2010-07-14 15:35:58 UTC (rev 21728)
Changed blocks: 3, Lines Added: 1132, Lines Deleted: 1126; 83198 bytes

@@ -8652,1134 +8652,12 @@
 
   </section>
 
-  <section id="locking-issues">
+  <section id="optimization-indexes">
 
-    <title>Locking Issues</title>
+    <title>Optimization and Indexes</title>
 
-    <para>
-      MySQL manages contention for table contents using locking:
-    </para>
+    <section id="column-indexes">
 
-    <itemizedlist>
-
-      <listitem>
-        <para>
-          Internal locking is performed within the MySQL server itself
-          to manage contention for table contents by multiple threads.
-          This type of locking is internal because it is performed
-          entirely by the server and involves no other programs. See
-          <xref linkend="internal-locking"/>.
-        </para>
-      </listitem>
-
-      <listitem>
-        <para>
-          External locking occurs when the server and other programs
-          lock table files to coordinate among themselves which program
-          can access the tables at which time. See
-          <xref linkend="external-locking"/>.
-        </para>
-      </listitem>
-
-    </itemizedlist>
-
-    <section id="internal-locking">
-
-      <title>Internal Locking Methods</title>
-
-      <indexterm>
-        <primary>internal locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>internal</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking methods</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>methods</primary>
-        <secondary>locking</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>row-level locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>table-level locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>row-level</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>table-level</secondary>
-      </indexterm>
-
-      <para>
-        This section discusses internal locking; that is, locking
-        performed within the MySQL server itself to manage contention
-        for table contents by multiple sessions. This type of locking is
-        internal because it is performed entirely by the server and
-        involves no other programs. External locking occurs when the
-        server and other programs lock table files to coordinate among
-        themselves which program can access the tables at which time.
-        See <xref linkend="external-locking"/>.
-      </para>
-
-      <para>
-        MySQL uses table-level locking for <literal>MyISAM</literal>,
-        <literal>MEMORY</literal>, and <literal>MERGE</literal> tables,
-        and row-level locking for <literal>InnoDB</literal> tables.
-      </para>
-
-      <para>
-        In many cases, you can make an educated guess about which
-        locking type is best for an application, but generally it is
-        difficult to say that a given lock type is better than another.
-        Everything depends on the application and different parts of an
-        application may require different lock types.
-      </para>
-
-      <para>
-        To decide whether you want to use a storage engine with
-        row-level locking, you should look at what your application does
-        and what mix of select and update statements it uses. For
-        example, most Web applications perform many selects, relatively
-        few deletes, updates based mainly on key values, and inserts
-        into a few specific tables. The base MySQL
-        <literal>MyISAM</literal> setup is very well tuned for this.
-      </para>
-
-      <formalpara role="mnmas">
-
-        <title>MySQL Enterprise</title>
-
-        <para>
-          The MySQL Enterprise Monitor provides expert advice on when to
-          use table-level locking and when to use row-level locking. To
-          subscribe, see &base-url-enterprise;advisors.html.
-        </para>
-
-      </formalpara>
-
-      <para>
-        Table locking in MySQL is deadlock-free for storage engines that
-        use table-level locking. Deadlock avoidance is managed by always
-        requesting all needed locks at once at the beginning of a query
-        and always locking the tables in the same order.
-      </para>
-
-      <para>
-        MySQL grants table write locks as follows:
-      </para>
-
-      <orderedlist>
-
-        <listitem>
-          <para>
-            If there are no locks on the table, put a write lock on it.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Otherwise, put the lock request in the write lock queue.
-          </para>
-        </listitem>
-
-      </orderedlist>
-
-      <para>
-        MySQL grants table read locks as follows:
-      </para>
-
-      <orderedlist>
-
-        <listitem>
-          <para>
-            If there are no write locks on the table, put a read lock on
-            it.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Otherwise, put the lock request in the read lock queue.
-          </para>
-        </listitem>
-
-      </orderedlist>
-
-      <para>
-        Table updates are given higher priority than table retrievals.
-        Therefore, when a lock is released, the lock is made available
-        to the requests in the write lock queue and then to the requests
-        in the read lock queue. This ensures that updates to a table are
-        not <quote>starved</quote> even if there is heavy
-        <literal role="stmt">SELECT</literal> activity for the table.
-        However, if you have many updates for a table,
-        <literal role="stmt">SELECT</literal> statements wait until
-        there are no more updates.
-      </para>
-
-      <para>
-        For information on altering the priority of reads and writes,
-        see <xref linkend="table-locking"/>.
-      </para>
-
-      <para>
-        You can analyze the table lock contention on your system by
-        checking the
-        <literal role="statvar">Table_locks_immediate</literal> and
-        <literal role="statvar">Table_locks_waited</literal> status
-        variables, which indicate the number of times that requests for
-        table locks could be granted immediately and the number that had
-        to wait, respectively:
-      </para>
-
-<programlisting>
-mysql&gt; <userinput>SHOW STATUS LIKE 'Table%';</userinput>
-+-----------------------+---------+
-| Variable_name         | Value   |
-+-----------------------+---------+
-| Table_locks_immediate | 1151552 |
-| Table_locks_waited    | 15324   |
-+-----------------------+---------+
-</programlisting>
-
-      <indexterm>
-        <primary>concurrent inserts</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>inserts</primary>
-        <secondary>concurrent</secondary>
-      </indexterm>
-
-      <para>
-        The <literal>MyISAM</literal> storage engine supports concurrent
-        inserts to reduce contention between readers and writers for a
-        given table: If a <literal>MyISAM</literal> table has no free
-        blocks in the middle of the data file, rows are always inserted
-        at the end of the data file. In this case, you can freely mix
-        concurrent <literal role="stmt">INSERT</literal> and
-        <literal role="stmt">SELECT</literal> statements for a
-        <literal>MyISAM</literal> table without locks. That is, you can
-        insert rows into a <literal>MyISAM</literal> table at the same
-        time other clients are reading from it. Holes can result from
-        rows having been deleted from or updated in the middle of the
-        table. If there are holes, concurrent inserts are disabled but
-        are enabled again automatically when all holes have been filled
-        with new data.. This behavior is altered by the
-        <literal role="sysvar">concurrent_insert</literal> system
-        variable. See <xref linkend="concurrent-inserts"/>.
-      </para>
-
-      <para>
-        If you acquire a table lock explicitly with
-        <literal role="stmt">LOCK TABLES</literal>, you can request a
-        <literal>READ LOCAL</literal> lock rather than a
-        <literal>READ</literal> lock to enable other sessions to perform
-        concurrent inserts while you have the table locked.
-      </para>
-
-      <para>
-        To perform many <literal role="stmt">INSERT</literal> and
-        <literal role="stmt">SELECT</literal> operations on a table
-        <literal>real_table</literal> when concurrent inserts are not
-        possible, you can insert rows into a temporary table
-        <literal>temp_table</literal> and update the real table with the
-        rows from the temporary table periodically. This can be done
-        with the following code:
-      </para>
-
-<programlisting>
-mysql&gt; <userinput>LOCK TABLES real_table WRITE, temp_table WRITE;</userinput>
-mysql&gt; <userinput>INSERT INTO real_table SELECT * FROM temp_table;</userinput>
-mysql&gt; <userinput>DELETE FROM temp_table;</userinput>
-mysql&gt; <userinput>UNLOCK TABLES;</userinput>
-</programlisting>
-
-      <para>
-        <literal>InnoDB</literal> uses row locks. Deadlocks are possible
-        for <literal>InnoDB</literal> because it automatically acquires
-        locks during the processing of SQL statements, not at the start
-        of the transaction.
-      </para>
-
-      <para>
-        Advantages of row-level locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Fewer lock conflicts when different sessions access
-            different rows
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Fewer changes for rollbacks
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Possible to lock a single row for a long time
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Disadvantages of row-level locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Requires more memory than table-level locks
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Slower than table-level locks when used on a large part of
-            the table because you must acquire many more locks
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Slower than other locks if you often do <literal>GROUP
-            BY</literal> operations on a large part of the data or if
-            you must scan the entire table frequently
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Generally, table locks are superior to row-level locks in the
-        following cases:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Most statements for the table are reads
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Statements for the table are a mix of reads and writes,
-            where writes are updates or deletes for a single row that
-            can be fetched with one key read:
-          </para>
-
-<programlisting>
-UPDATE <replaceable>tbl_name</replaceable> SET <replaceable>column</replaceable>=<replaceable>value</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
-DELETE FROM <replaceable>tbl_name</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
-</programlisting>
-        </listitem>
-
-        <listitem>
-          <para>
-            <literal role="stmt">SELECT</literal> combined with
-            concurrent <literal role="stmt">INSERT</literal> statements,
-            and very few <literal role="stmt">UPDATE</literal> or
-            <literal role="stmt">DELETE</literal> statements
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Many scans or <literal>GROUP BY</literal> operations on the
-            entire table without any writers
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        With higher-level locks, you can more easily tune applications
-        by supporting locks of different types, because the lock
-        overhead is less than for row-level locks.
-      </para>
-
-      <para>
-        Options other than row-level locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Versioning (such as that used in MySQL for concurrent
-            inserts) where it is possible to have one writer at the same
-            time as many readers. This means that the database or table
-            supports different views for the data depending on when
-            access begins. Other common terms for this are <quote>time
-            travel,</quote> <quote>copy on write,</quote> or <quote>copy
-            on demand.</quote>
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Copy on demand is in many cases superior to row-level
-            locking. However, in the worst case, it can use much more
-            memory than using normal locks.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Instead of using row-level locks, you can employ
-            application-level locks, such as those provided by
-            <literal role="func">GET_LOCK()</literal> and
-            <literal role="func">RELEASE_LOCK()</literal> in MySQL.
-            These are advisory locks, so they work only with
-            applications that cooperate with each other. See
-            <xref linkend="miscellaneous-functions"/>.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-    </section>
-
-    <section id="table-locking">
-
-      <title>Table Locking Issues</title>
-
-      <indexterm>
-        <primary>problems</primary>
-        <secondary>table locking</secondary>
-      </indexterm>
-
-      <para>
-        To achieve a very high lock speed, MySQL uses table locking
-        (instead of page, row, or column locking) for all storage
-        engines except <literal>InnoDB</literal> and
-        <literal role="se">NDBCLUSTER</literal>.
-      </para>
-
-      <para>
-        For <literal>InnoDB</literal> tables, MySQL uses table locking
-        only if you explicitly lock the table with
-        <literal role="stmt">LOCK TABLES</literal>. For this storage
-        engine, avoid using <literal role="stmt">LOCK TABLES</literal>
-        at all, because <literal>InnoDB</literal> uses automatic
-        row-level locking to ensure transaction isolation.
-      </para>
-
-      <para>
-        For large tables, table locking is often better than row
-        locking, but there are some disadvantages:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Table locking enables many sessions to read from a table at
-            the same time, but if a session wants to write to a table,
-            it must first get exclusive access. During the update, all
-            other sessions that want to access this particular table
-            must wait until the update is done.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Table locking causes problems in cases such as when a
-            session is waiting because the disk is full and free space
-            needs to become available before the session can proceed. In
-            this case, all sessions that want to access the problem
-            table are also put in a waiting state until more disk space
-            is made available.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Table locking is also disadvantageous under the following
-        scenario:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            A session issues a <literal role="stmt">SELECT</literal>
-            that takes a long time to run.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Another session then issues an
-            <literal role="stmt">UPDATE</literal> on the same table.
-            This session waits until the
-            <literal role="stmt">SELECT</literal> is finished.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Another session issues another
-            <literal role="stmt">SELECT</literal> statement on the same
-            table. Because <literal role="stmt">UPDATE</literal> has
-            higher priority than <literal role="stmt">SELECT</literal>,
-            this <literal role="stmt">SELECT</literal> waits for the
-            <literal role="stmt">UPDATE</literal> to finish,
-            <emphasis>after</emphasis> waiting for the first
-            <literal role="stmt">SELECT</literal> to finish.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        The following items describe some ways to avoid or reduce
-        contention caused by table locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Try to get the <literal role="stmt">SELECT</literal>
-            statements to run faster so that they lock tables for a
-            shorter time. You might have to create some summary tables
-            to do this.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Start <command>mysqld</command> with
-            <option role="mysqld">--low-priority-updates</option>. For
-            storage engines that use only table-level locking (such as
-            <literal>MyISAM</literal>, <literal>MEMORY</literal>, and
-            <literal>MERGE</literal>), this gives all statements that
-            update (modify) a table lower priority than
-            <literal role="stmt">SELECT</literal> statements. In this
-            case, the second <literal role="stmt">SELECT</literal>
-            statement in the preceding scenario would execute before the
-            <literal role="stmt">UPDATE</literal> statement, and would
-            not need to wait for the first
-            <literal role="stmt">SELECT</literal> to finish.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            To specify that all updates issued in a specific connection
-            should be done with low priority, set the
-            <literal role="sysvar">low_priority_updates</literal> server
-            system variable equal to 1.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            To give a specific <literal role="stmt">INSERT</literal>,
-            <literal role="stmt">UPDATE</literal>, or
-            <literal role="stmt">DELETE</literal> statement lower
-            priority, use the <literal>LOW_PRIORITY</literal> attribute.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            To give a specific <literal role="stmt">SELECT</literal>
-            statement higher priority, use the
-            <literal>HIGH_PRIORITY</literal> attribute. See
-            <xref linkend="select"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Start <command>mysqld</command> with a low value for the
-            <literal role="sysvar">max_write_lock_count</literal> system
-            variable to force MySQL to temporarily elevate the priority
-            of all <literal role="stmt">SELECT</literal> statements that
-            are waiting for a table after a specific number of inserts
-            to the table occur. This permits <literal>READ</literal>
-            locks after a certain number of <literal>WRITE</literal>
-            locks.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you have problems with
-            <literal role="stmt">INSERT</literal> combined with
-            <literal role="stmt">SELECT</literal>, consider switching to
-            <literal>MyISAM</literal> tables, which support concurrent
-            <literal role="stmt">SELECT</literal> and
-            <literal role="stmt">INSERT</literal> statements. (See
-            <xref linkend="concurrent-inserts"/>.)
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you mix inserts and deletes on the same table,
-            <literal role="stmt">INSERT DELAYED</literal> may be of
-            great help. See <xref linkend="insert-delayed"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you have problems with mixed
-            <literal role="stmt">SELECT</literal> and
-            <literal role="stmt">DELETE</literal> statements, the
-            <literal>LIMIT</literal> option to
-            <literal role="stmt">DELETE</literal> may help. See
-            <xref linkend="delete"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Using <literal>SQL_BUFFER_RESULT</literal> with
-            <literal role="stmt">SELECT</literal> statements can help to
-            make the duration of table locks shorter. See
-            <xref linkend="select"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            You could change the locking code in
-            <filename>mysys/thr_lock.c</filename> to use a single queue.
-            In this case, write locks and read locks would have the same
-            priority, which might help some applications.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Here are some tips concerning table locks in MySQL:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Concurrent users are not a problem if you do not mix updates
-            with selects that need to examine many rows in the same
-            table.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            You can use <literal role="stmt">LOCK TABLES</literal> to
-            increase speed, because many updates within a single lock is
-            much faster than updating without locks. Splitting table
-            contents into separate tables may also help.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you encounter speed problems with table locks in MySQL,
-            you may be able to improve performance by converting some of
-            your tables to <literal>InnoDB</literal>. See
-            <xref linkend="innodb"/>.
-          </para>
-
-          <formalpara role="mnmas">
-
-            <title>MySQL Enterprise</title>
-
-            <para>
-              Lock contention can seriously degrade performance. The
-              MySQL Enterprise Monitor provides expert advice on
-              avoiding this problem. To subscribe, see
-              &base-url-enterprise;advisors.html.
-            </para>
-
-          </formalpara>
-        </listitem>
-
-      </itemizedlist>
-
-    </section>
-
-    <section id="concurrent-inserts">
-
-      <title>Concurrent Inserts</title>
-
-      <indexterm>
-        <primary>concurrent inserts</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>inserts</primary>
-        <secondary>concurrent</secondary>
-      </indexterm>
-
-      <para>
-        The <literal>MyISAM</literal> storage engine supports concurrent
-        inserts to reduce contention between readers and writers for a
-        given table: If a <literal>MyISAM</literal> table has no holes
-        in the data file (deleted rows in the middle), an
-        <literal role="stmt">INSERT</literal> statement can be executed
-        to add rows to the end of the table at the same time that
-        <literal role="stmt">SELECT</literal> statements are reading
-        rows from the table. If there are multiple
-        <literal role="stmt">INSERT</literal> statements, they are
-        queued and performed in sequence, concurrently with the
-        <literal role="stmt">SELECT</literal> statements. The results of
-        a concurrent <literal role="stmt">INSERT</literal> may not be
-        visible immediately.
-      </para>
-
-      <para>
-        The <literal role="sysvar">concurrent_insert</literal> system
-        variable can be set to modify the concurrent-insert processing.
-        By default, the variable is set to 1 and concurrent inserts are
-        handled as just described. If
-        <literal role="sysvar">concurrent_insert</literal> is set to 0,
-        concurrent inserts are disabled. If the variable is set to 2,
-        concurrent inserts at the end of the table are allowed even for
-        tables that have deleted rows. See also the description of the
-        <link linkend="sysvar_concurrent_insert"><literal role="sysvar">concurrent_insert</literal></link>
-        system variable.
-      </para>
-
-      <para>
-        Under circumstances where concurrent inserts can be used, there
-        is seldom any need to use the <literal>DELAYED</literal>
-        modifier for <literal role="stmt">INSERT</literal> statements.
-        See <xref linkend="insert-delayed"/>.
-      </para>
-
-      <para>
-        If you are using the binary log, concurrent inserts are
-        converted to normal inserts for <literal>CREATE ...
-        SELECT</literal> or
-        <literal role="stmt" condition="insert-select">INSERT ...
-        SELECT</literal> statements. This is done to ensure that you can
-        re-create an exact copy of your tables by applying the log
-        during a backup operation. See <xref linkend="binary-log"/>. In
-        addition, for those statements a read lock is placed on the
-        selected-from table such that inserts into that table are
-        blocked. The effect is that concurrent inserts for that table
-        must wait as well.
-      </para>
-
-      <para>
-        With <literal role="stmt" condition="load-data">LOAD DATA
-        INFILE</literal>, if you specify <literal>CONCURRENT</literal>
-        with a <literal>MyISAM</literal> table that satisfies the
-        condition for concurrent inserts (that is, it contains no free
-        blocks in the middle), other sessions can retrieve data from the
-        table while <literal role="stmt">LOAD DATA</literal> is
-        executing. Use of the <literal>CONCURRENT</literal> option
-        affects the performance of <literal role="stmt">LOAD
-        DATA</literal> a bit, even if no other session is using the
-        table at the same time.
-      </para>
-
-      <para>
-        If you specify <literal>HIGH_PRIORITY</literal>, it overrides
-        the effect of the
-        <option role="mysqld">--low-priority-updates</option> option if
-        the server was started with that option. It also causes
-        concurrent inserts not to be used.
-      </para>
-
-      <para>
-        For <literal role="stmt" condition="lock-tables">LOCK
-        TABLE</literal>, the difference between <literal>READ
-        LOCAL</literal> and <literal>READ</literal> is that
-        <literal>READ LOCAL</literal> permits nonconflicting
-        <literal role="stmt">INSERT</literal> statements (concurrent
-        inserts) to execute while the lock is held. However, this cannot
-        be used if you are going to manipulate the database using
-        processes external to the server while you hold the lock.
-      </para>
-
-    </section>
-
-    <section id="external-locking">
-
-      <title>External Locking</title>
-
-      <indexterm>
-        <primary>external locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>external</secondary>
-      </indexterm>
-
-      <para>
-        External locking is the use of file system locking to manage
-        contention for database tables by multiple processes. External
-        locking is used in situations where a single process such as the
-        MySQL server cannot be assumed to be the only process that
-        requires access to tables. Here are some examples:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            If you run multiple servers that use the same database
-            directory (not recommended), each server must have external
-            locking enabled.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you use <command>myisamchk</command> to perform table
-            maintenance operations on <literal>MyISAM</literal> tables,
-            you must either ensure that the server is not running, or
-            that the server has external locking enabled so that it
-            locks table files as necessary to coordinate with
-            <command>myisamchk</command> for access to the tables. The
-            same is true for use of <command>myisampack</command> to
-            pack <literal>MyISAM</literal> tables.
-          </para>
-
-          <para>
-            If the server is run with external locking enabled, you can
-            use <command>myisamchk</command> at any time for read
-            operations such a checking tables. In this case, if the
-            server tries to update a table that
-            <command>myisamchk</command> is using, the server will wait
-            for <command>myisamchk</command> to finish before it
-            continues.
-          </para>
-
-          <para>
-            If you use <command>myisamchk</command> for write operations
-            such as repairing or optimizing tables, or if you use
-            <command>myisampack</command> to pack tables, you
-            <emphasis>must</emphasis> always ensure that the
-            <command>mysqld</command> server is not using the table. If
-            you don't stop <command>mysqld</command>, you should at
-            least do a <command>mysqladmin flush-tables</command> before
-            you run <command>myisamchk</command>. Your tables
-            <emphasis>may become corrupted</emphasis> if the server and
-            <command>myisamchk</command> access the tables
-            simultaneously.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        With external locking in effect, each process that requires
-        access to a table acquires a file system lock for the table
-        files before proceeding to access the table. If all necessary
-        locks cannot be acquired, the process is blocked from accessing
-        the table until the locks can be obtained (after the process
-        that currently holds the locks releases them).
-      </para>
-
-      <para>
-        External locking affects server performance because the server
-        must sometimes wait for other processes before it can access
-        tables.
-      </para>
-
-      <para>
-        External locking is unnecessary if you run a single server to
-        access a given data directory (which is the usual case) and if
-        no other programs such as <command>myisamchk</command> need to
-        modify tables while the server is running. If you only
-        <emphasis>read</emphasis> tables with other programs, external
-        locking is not required, although <command>myisamchk</command>
-        might report warnings if the server changes tables while
-        <command>myisamchk</command> is reading them.
-      </para>
-
-      <para>
-        With external locking disabled, to use
-        <command>myisamchk</command>, you must either stop the server
-        while <command>myisamchk</command> executes or else lock and
-        flush the tables before running <command>myisamchk</command>.
-        (See <xref linkend="system-optimization"/>.) To avoid this
-        requirement, use the <literal role="stmt">CHECK TABLE</literal>
-        and <literal role="stmt">REPAIR TABLE</literal> statements to
-        check and repair <literal>MyISAM</literal> tables.
-      </para>
-
-      <para>
-        For <command>mysqld</command>, external locking is controlled by
-        the value of the
-        <literal role="sysvar">skip_external_locking</literal> system
-        variable. When this variable is enabled, external locking is
-        disabled, and vice versa. From MySQL 4.0 on, external locking is
-        disabled by default. Before MySQL 4.0, external locking is
-        enabled by default on Linux or when MySQL is configured to use
-        MIT-pthreads.
-      </para>
-
-      <para>
-        Use of external locking can be controlled at server startup by
-        using the <option role="mysqld">--external-locking</option> or
-        <option role="mysqld">--skip-external-locking</option> option.
-      </para>
-
-      <para>
-        If you do use external locking option to enable updates to
-        <literal>MyISAM</literal> tables from many MySQL processes, you
-        must ensure that the following conditions are satisfied:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            You should not use the query cache for queries that use
-            tables that are updated by another process.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            You should not start the server with the
-            <option role="mysqld">--delay-key-write=ALL</option> option
-            or use the <literal>DELAY_KEY_WRITE=1</literal> table option
-            for any shared tables. Otherwise, index corruption can
-            occur.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        The easiest way to satisfy these conditions is to always use
-        <option role="mysqld">--external-locking</option> together with
-        <option role="mysqld">--delay-key-write=OFF</option> and
-        <option role="sysvar">--query-cache-size=0</option>. (This is
-        not done by default because in many setups it is useful to have
-        a mixture of the preceding options.)
-      </para>
-
-    </section>
-
-  </section>
-
-  <section id="optimizing-database-structure">
-
-    <title>Optimizing Database Structure</title>
-
-    <section id="data-size">
-
-      <title>Make Your Data as Small as Possible</title>
-
-      <indexterm>
-        <primary>data</primary>
-        <secondary>size</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>reducing</primary>
-        <secondary>data size</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>storage space</primary>
-        <secondary>minimizing</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>tables</primary>
-        <secondary>improving performance</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>performance</primary>
-        <secondary>improving</secondary>
-      </indexterm>
-
-      <para>
-        One of the most basic optimizations is to design your tables to
-        take as little space on the disk as possible. This can result in
-        huge improvements because disk reads are faster, and smaller
-        tables normally require less main memory while their contents
-        are being actively processed during query execution. Indexing
-        also is a lesser resource burden if done on smaller columns.
-      </para>
-
-      <para>
-        MySQL supports many different storage engines (table types) and
-        row formats. For each table, you can decide which storage and
-        indexing method to use. Choosing the proper table format for
-        your application may give you a big performance gain. See
-        <xref linkend="storage-engines"/>.
-      </para>
-
-      <para>
-        You can get better performance for a table and minimize storage
-        space by using the techniques listed here:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Use the most efficient (smallest) data types possible. MySQL
-            has many specialized types that save disk space and memory.
-            For example, use the smaller integer types if possible to
-            get smaller tables. <literal role="type">MEDIUMINT</literal>
-            is often a better choice than
-            <literal role="type">INT</literal> because a
-            <literal role="type">MEDIUMINT</literal> column uses 25%
-            less space.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Declare columns to be <literal>NOT NULL</literal> if
-            possible. It makes everything faster and you save one bit
-            per column. If you really need <literal>NULL</literal> in
-            your application, you should definitely use it. Just avoid
-            having it on all columns by default.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            For <literal>MyISAM</literal> tables, if you do not have any
-            variable-length columns
-            (<literal role="type">VARCHAR</literal>,
-            <literal role="type">TEXT</literal>, or
-            <literal role="type">BLOB</literal> columns), a fixed-size
-            row format is used. This is faster but unfortunately may
-            waste some space. See
-            <xref linkend="myisam-table-formats"/>. You can hint that
-            you want to have fixed length rows even if you have
-            <literal role="type">VARCHAR</literal> columns with the
-            <literal role="stmt">CREATE TABLE</literal> option
-            <literal>ROW_FORMAT=FIXED</literal>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            <literal>InnoDB</literal> tables use a compact storage
-            format. In versions of MySQL earlier than 5.0.3,
-            <literal>InnoDB</literal> rows contain some redundant
-            information, such as the number of columns and the length of
-            each column, even for fixed-size columns. By default, tables
-            are created in the compact format
-            (<literal>ROW_FORMAT=COMPACT</literal>). If you wish to
-            downgrade to older versions of MySQL, you can request the
-            old format with <literal>ROW_FORMAT=REDUNDANT</literal>.
-          </para>
-
-          <para>
-            The presence of the compact row format decreases row storage
-            space by about 20% at the cost of increasing CPU use for
-            some operations. If your workload is a typical one that is
-            limited by cache hit rates and disk speed it is likely to be
-            faster. If it is a rare case that is limited by CPU speed,
-            it might be slower.
-          </para>
-
-          <para>
-            The compact <literal>InnoDB</literal> format also changes
-            how <literal role="type">CHAR</literal> columns containing
-            UTF-8 data are stored. With
-            <literal>ROW_FORMAT=REDUNDANT</literal>, a UTF-8
-            <literal>CHAR(<replaceable>N</replaceable>)</literal>
-            occupies 3 &times; <replaceable>N</replaceable> bytes, given
-            that the maximum length of a UTF-8 encoded character is
-            three bytes. Many languages can be written primarily using
-            single-byte UTF-8 characters, so a fixed storage length
-            often wastes space. With
-            <literal>ROW_FORMAT=COMPACT</literal> format,
-            <literal>InnoDB</literal> allocates a variable amount of
-            storage in the range from <replaceable>N</replaceable> to 3
-            &times; <replaceable>N</replaceable> bytes for these columns
-            by stripping trailing spaces if necessary. The minimum
-            storage length is kept as <replaceable>N</replaceable> bytes
-            to facilitate in-place updates in typical cases.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            The primary index of a table should be as short as possible.
-            This makes identification of each row easy and efficient.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Create only the indexes that you really need. Indexes are
-            good for retrieval but bad when you need to store data
-            quickly. If you access a table mostly by searching on a
-            combination of columns, create an index on them. The first
-            part of the index should be the column most used. If you
-            <emphasis>always</emphasis> use many columns when selecting
-            from the table, the first column in the index should be the
-            one with the most duplicates to obtain better compression of
-            the index.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If it is very likely that a string column has a unique
-            prefix on the first number of characters, it is better to
-            index only this prefix, using MySQL's support for creating
-            an index on the leftmost part of the column (see
-            <xref linkend="create-index"/>). Shorter indexes are faster,
-            not only because they require less disk space, but because
-            they also give you more hits in the index cache, and thus
-            fewer disk seeks. See <xref linkend="server-parameters"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            In some circumstances, it can be beneficial to split into
-            two a table that is scanned very often. This is especially
-            true if it is a dynamic-format table and it is possible to
-            use a smaller static format table that can be used to find
-            the relevant rows when scanning the table.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-    </section>
-
-    <section id="indexes">
-
       <title>Column Indexes</title>
 
       <indexterm>

@@ -9909,7 +8787,7 @@
         MySQL can create composite indexes (that is, indexes on multiple
         columns). An index may consist of up to 16 columns. For certain
         data types, you can index a prefix of the column (see
-        <xref linkend="indexes"/>).
+        <xref linkend="column-indexes"/>).
       </para>
 
       <para>

@@ -11613,6 +10491,1134 @@
 
     </section>
 
+  </section>
+
+  <section id="locking-issues">
+
+    <title>Locking Issues</title>
+
+    <para>
+      MySQL manages contention for table contents using locking:
+    </para>
+
+    <itemizedlist>
+
+      <listitem>
+        <para>
+          Internal locking is performed within the MySQL server itself
+          to manage contention for table contents by multiple threads.
+          This type of locking is internal because it is performed
+          entirely by the server and involves no other programs. See
+          <xref linkend="internal-locking"/>.
+        </para>
+      </listitem>
+
+      <listitem>
+        <para>
+          External locking occurs when the server and other programs
+          lock table files to coordinate among themselves which program
+          can access the tables at which time. See
+          <xref linkend="external-locking"/>.
+        </para>
+      </listitem>
+
+    </itemizedlist>
+
+    <section id="internal-locking">
+
+      <title>Internal Locking Methods</title>
+
+      <indexterm>
+        <primary>internal locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>internal</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking methods</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>methods</primary>
+        <secondary>locking</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>row-level locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>table-level locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>row-level</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>table-level</secondary>
+      </indexterm>
+
+      <para>
+        This section discusses internal locking; that is, locking
+        performed within the MySQL server itself to manage contention
+        for table contents by multiple sessions. This type of locking is
+        internal because it is performed entirely by the server and
+        involves no other programs. External locking occurs when the
+        server and other programs lock table files to coordinate among
+        themselves which program can access the tables at which time.
+        See <xref linkend="external-locking"/>.
+      </para>
+
+      <para>
+        MySQL uses table-level locking for <literal>MyISAM</literal>,
+        <literal>MEMORY</literal>, and <literal>MERGE</literal> tables,
+        and row-level locking for <literal>InnoDB</literal> tables.
+      </para>
+
+      <para>
+        In many cases, you can make an educated guess about which
+        locking type is best for an application, but generally it is
+        difficult to say that a given lock type is better than another.
+        Everything depends on the application and different parts of an
+        application may require different lock types.
+      </para>
+
+      <para>
+        To decide whether you want to use a storage engine with
+        row-level locking, you should look at what your application does
+        and what mix of select and update statements it uses. For
+        example, most Web applications perform many selects, relatively
+        few deletes, updates based mainly on key values, and inserts
+        into a few specific tables. The base MySQL
+        <literal>MyISAM</literal> setup is very well tuned for this.
+      </para>
+
+      <formalpara role="mnmas">
+
+        <title>MySQL Enterprise</title>
+
+        <para>
+          The MySQL Enterprise Monitor provides expert advice on when to
+          use table-level locking and when to use row-level locking. To
+          subscribe, see &base-url-enterprise;advisors.html.
+        </para>
+
+      </formalpara>
+
+      <para>
+        Table locking in MySQL is deadlock-free for storage engines that
+        use table-level locking. Deadlock avoidance is managed by always
+        requesting all needed locks at once at the beginning of a query
+        and always locking the tables in the same order.
+      </para>
+
+      <para>
+        MySQL grants table write locks as follows:
+      </para>
+
+      <orderedlist>
+
+        <listitem>
+          <para>
+            If there are no locks on the table, put a write lock on it.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Otherwise, put the lock request in the write lock queue.
+          </para>
+        </listitem>
+
+      </orderedlist>
+
+      <para>
+        MySQL grants table read locks as follows:
+      </para>
+
+      <orderedlist>
+
+        <listitem>
+          <para>
+            If there are no write locks on the table, put a read lock on
+            it.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Otherwise, put the lock request in the read lock queue.
+          </para>
+        </listitem>
+
+      </orderedlist>
+
+      <para>
+        Table updates are given higher priority than table retrievals.
+        Therefore, when a lock is released, the lock is made available
+        to the requests in the write lock queue and then to the requests
+        in the read lock queue. This ensures that updates to a table are
+        not <quote>starved</quote> even if there is heavy
+        <literal role="stmt">SELECT</literal> activity for the table.
+        However, if you have many updates for a table,
+        <literal role="stmt">SELECT</literal> statements wait until
+        there are no more updates.
+      </para>
+
+      <para>
+        For information on altering the priority of reads and writes,
+        see <xref linkend="table-locking"/>.
+      </para>
+
+      <para>
+        You can analyze the table lock contention on your system by
+        checking the
+        <literal role="statvar">Table_locks_immediate</literal> and
+        <literal role="statvar">Table_locks_waited</literal> status
+        variables, which indicate the number of times that requests for
+        table locks could be granted immediately and the number that had
+        to wait, respectively:
+      </para>
+
+<programlisting>
+mysql&gt; <userinput>SHOW STATUS LIKE 'Table%';</userinput>
++-----------------------+---------+
+| Variable_name         | Value   |
++-----------------------+---------+
+| Table_locks_immediate | 1151552 |
+| Table_locks_waited    | 15324   |
++-----------------------+---------+
+</programlisting>
+
+      <indexterm>
+        <primary>concurrent inserts</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>inserts</primary>
+        <secondary>concurrent</secondary>
+      </indexterm>
+
+      <para>
+        The <literal>MyISAM</literal> storage engine supports concurrent
+        inserts to reduce contention between readers and writers for a
+        given table: If a <literal>MyISAM</literal> table has no free
+        blocks in the middle of the data file, rows are always inserted
+        at the end of the data file. In this case, you can freely mix
+        concurrent <literal role="stmt">INSERT</literal> and
+        <literal role="stmt">SELECT</literal> statements for a
+        <literal>MyISAM</literal> table without locks. That is, you can
+        insert rows into a <literal>MyISAM</literal> table at the same
+        time other clients are reading from it. Holes can result from
+        rows having been deleted from or updated in the middle of the
+        table. If there are holes, concurrent inserts are disabled but
+        are enabled again automatically when all holes have been filled
+        with new data.. This behavior is altered by the
+        <literal role="sysvar">concurrent_insert</literal> system
+        variable. See <xref linkend="concurrent-inserts"/>.
+      </para>
+
+      <para>
+        If you acquire a table lock explicitly with
+        <literal role="stmt">LOCK TABLES</literal>, you can request a
+        <literal>READ LOCAL</literal> lock rather than a
+        <literal>READ</literal> lock to enable other sessions to perform
+        concurrent inserts while you have the table locked.
+      </para>
+
+      <para>
+        To perform many <literal role="stmt">INSERT</literal> and
+        <literal role="stmt">SELECT</literal> operations on a table
+        <literal>real_table</literal> when concurrent inserts are not
+        possible, you can insert rows into a temporary table
+        <literal>temp_table</literal> and update the real table with the
+        rows from the temporary table periodically. This can be done
+        with the following code:
+      </para>
+
+<programlisting>
+mysql&gt; <userinput>LOCK TABLES real_table WRITE, temp_table WRITE;</userinput>
+mysql&gt; <userinput>INSERT INTO real_table SELECT * FROM temp_table;</userinput>
+mysql&gt; <userinput>DELETE FROM temp_table;</userinput>
+mysql&gt; <userinput>UNLOCK TABLES;</userinput>
+</programlisting>
+
+      <para>
+        <literal>InnoDB</literal> uses row locks. Deadlocks are possible
+        for <literal>InnoDB</literal> because it automatically acquires
+        locks during the processing of SQL statements, not at the start
+        of the transaction.
+      </para>
+
+      <para>
+        Advantages of row-level locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Fewer lock conflicts when different sessions access
+            different rows
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Fewer changes for rollbacks
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Possible to lock a single row for a long time
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Disadvantages of row-level locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Requires more memory than table-level locks
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Slower than table-level locks when used on a large part of
+            the table because you must acquire many more locks
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Slower than other locks if you often do <literal>GROUP
+            BY</literal> operations on a large part of the data or if
+            you must scan the entire table frequently
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Generally, table locks are superior to row-level locks in the
+        following cases:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Most statements for the table are reads
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Statements for the table are a mix of reads and writes,
+            where writes are updates or deletes for a single row that
+            can be fetched with one key read:
+          </para>
+
+<programlisting>
+UPDATE <replaceable>tbl_name</replaceable> SET <replaceable>column</replaceable>=<replaceable>value</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
+DELETE FROM <replaceable>tbl_name</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
+</programlisting>
+        </listitem>
+
+        <listitem>
+          <para>
+            <literal role="stmt">SELECT</literal> combined with
+            concurrent <literal role="stmt">INSERT</literal> statements,
+            and very few <literal role="stmt">UPDATE</literal> or
+            <literal role="stmt">DELETE</literal> statements
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Many scans or <literal>GROUP BY</literal> operations on the
+            entire table without any writers
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        With higher-level locks, you can more easily tune applications
+        by supporting locks of different types, because the lock
+        overhead is less than for row-level locks.
+      </para>
+
+      <para>
+        Options other than row-level locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Versioning (such as that used in MySQL for concurrent
+            inserts) where it is possible to have one writer at the same
+            time as many readers. This means that the database or table
+            supports different views for the data depending on when
+            access begins. Other common terms for this are <quote>time
+            travel,</quote> <quote>copy on write,</quote> or <quote>copy
+            on demand.</quote>
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Copy on demand is in many cases superior to row-level
+            locking. However, in the worst case, it can use much more
+            memory than using normal locks.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Instead of using row-level locks, you can employ
+            application-level locks, such as those provided by
+            <literal role="func">GET_LOCK()</literal> and
+            <literal role="func">RELEASE_LOCK()</literal> in MySQL.
+            These are advisory locks, so they work only with
+            applications that cooperate with each other. See
+            <xref linkend="miscellaneous-functions"/>.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+    </section>
+
+    <section id="table-locking">
+
+      <title>Table Locking Issues</title>
+
+      <indexterm>
+        <primary>problems</primary>
+        <secondary>table locking</secondary>
+      </indexterm>
+
+      <para>
+        To achieve a very high lock speed, MySQL uses table locking
+        (instead of page, row, or column locking) for all storage
+        engines except <literal>InnoDB</literal> and
+        <literal role="se">NDBCLUSTER</literal>.
+      </para>
+
+      <para>
+        For <literal>InnoDB</literal> tables, MySQL uses table locking
+        only if you explicitly lock the table with
+        <literal role="stmt">LOCK TABLES</literal>. For this storage
+        engine, avoid using <literal role="stmt">LOCK TABLES</literal>
+        at all, because <literal>InnoDB</literal> uses automatic
+        row-level locking to ensure transaction isolation.
+      </para>
+
+      <para>
+        For large tables, table locking is often better than row
+        locking, but there are some disadvantages:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Table locking enables many sessions to read from a table at
+            the same time, but if a session wants to write to a table,
+            it must first get exclusive access. During the update, all
+            other sessions that want to access this particular table
+            must wait until the update is done.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Table locking causes problems in cases such as when a
+            session is waiting because the disk is full and free space
+            needs to become available before the session can proceed. In
+            this case, all sessions that want to access the problem
+            table are also put in a waiting state until more disk space
+            is made available.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Table locking is also disadvantageous under the following
+        scenario:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            A session issues a <literal role="stmt">SELECT</literal>
+            that takes a long time to run.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Another session then issues an
+            <literal role="stmt">UPDATE</literal> on the same table.
+            This session waits until the
+            <literal role="stmt">SELECT</literal> is finished.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Another session issues another
+            <literal role="stmt">SELECT</literal> statement on the same
+            table. Because <literal role="stmt">UPDATE</literal> has
+            higher priority than <literal role="stmt">SELECT</literal>,
+            this <literal role="stmt">SELECT</literal> waits for the
+            <literal role="stmt">UPDATE</literal> to finish,
+            <emphasis>after</emphasis> waiting for the first
+            <literal role="stmt">SELECT</literal> to finish.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        The following items describe some ways to avoid or reduce
+        contention caused by table locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Try to get the <literal role="stmt">SELECT</literal>
+            statements to run faster so that they lock tables for a
+            shorter time. You might have to create some summary tables
+            to do this.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Start <command>mysqld</command> with
+            <option role="mysqld">--low-priority-updates</option>. For
+            storage engines that use only table-level locking (such as
+            <literal>MyISAM</literal>, <literal>MEMORY</literal>, and
+            <literal>MERGE</literal>), this gives all statements that
+            update (modify) a table lower priority than
+            <literal role="stmt">SELECT</literal> statements. In this
+            case, the second <literal role="stmt">SELECT</literal>
+            statement in the preceding scenario would execute before the
+            <literal role="stmt">UPDATE</literal> statement, and would
+            not need to wait for the first
+            <literal role="stmt">SELECT</literal> to finish.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            To specify that all updates issued in a specific connection
+            should be done with low priority, set the
+            <literal role="sysvar">low_priority_updates</literal> server
+            system variable equal to 1.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            To give a specific <literal role="stmt">INSERT</literal>,
+            <literal role="stmt">UPDATE</literal>, or
+            <literal role="stmt">DELETE</literal> statement lower
+            priority, use the <literal>LOW_PRIORITY</literal> attribute.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            To give a specific <literal role="stmt">SELECT</literal>
+            statement higher priority, use the
+            <literal>HIGH_PRIORITY</literal> attribute. See
+            <xref linkend="select"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Start <command>mysqld</command> with a low value for the
+            <literal role="sysvar">max_write_lock_count</literal> system
+            variable to force MySQL to temporarily elevate the priority
+            of all <literal role="stmt">SELECT</literal> statements that
+            are waiting for a table after a specific number of inserts
+            to the table occur. This permits <literal>READ</literal>
+            locks after a certain number of <literal>WRITE</literal>
+            locks.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you have problems with
+            <literal role="stmt">INSERT</literal> combined with
+            <literal role="stmt">SELECT</literal>, consider switching to
+            <literal>MyISAM</literal> tables, which support concurrent
+            <literal role="stmt">SELECT</literal> and
+            <literal role="stmt">INSERT</literal> statements. (See
+            <xref linkend="concurrent-inserts"/>.)
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you mix inserts and deletes on the same table,
+            <literal role="stmt">INSERT DELAYED</literal> may be of
+            great help. See <xref linkend="insert-delayed"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you have problems with mixed
+            <literal role="stmt">SELECT</literal> and
+            <literal role="stmt">DELETE</literal> statements, the
+            <literal>LIMIT</literal> option to
+            <literal role="stmt">DELETE</literal> may help. See
+            <xref linkend="delete"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Using <literal>SQL_BUFFER_RESULT</literal> with
+            <literal role="stmt">SELECT</literal> statements can help to
+            make the duration of table locks shorter. See
+            <xref linkend="select"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            You could change the locking code in
+            <filename>mysys/thr_lock.c</filename> to use a single queue.
+            In this case, write locks and read locks would have the same
+            priority, which might help some applications.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Here are some tips concerning table locks in MySQL:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Concurrent users are not a problem if you do not mix updates
+            with selects that need to examine many rows in the same
+            table.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            You can use <literal role="stmt">LOCK TABLES</literal> to
+            increase speed, because many updates within a single lock is
+            much faster than updating without locks. Splitting table
+            contents into separate tables may also help.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you encounter speed problems with table locks in MySQL,
+            you may be able to improve performance by converting some of
+            your tables to <literal>InnoDB</literal>. See
+            <xref linkend="innodb"/>.
+          </para>
+
+          <formalpara role="mnmas">
+
+            <title>MySQL Enterprise</title>
+
+            <para>
+              Lock contention can seriously degrade performance. The
+              MySQL Enterprise Monitor provides expert advice on
+              avoiding this problem. To subscribe, see
+              &base-url-enterprise;advisors.html.
+            </para>
+
+          </formalpara>
+        </listitem>
+
+      </itemizedlist>
+
+    </section>
+
+    <section id="concurrent-inserts">
+
+      <title>Concurrent Inserts</title>
+
+      <indexterm>
+        <primary>concurrent inserts</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>inserts</primary>
+        <secondary>concurrent</secondary>
+      </indexterm>
+
+      <para>
+        The <literal>MyISAM</literal> storage engine supports concurrent
+        inserts to reduce contention between readers and writers for a
+        given table: If a <literal>MyISAM</literal> table has no holes
+        in the data file (deleted rows in the middle), an
+        <literal role="stmt">INSERT</literal> statement can be executed
+        to add rows to the end of the table at the same time that
+        <literal role="stmt">SELECT</literal> statements are reading
+        rows from the table. If there are multiple
+        <literal role="stmt">INSERT</literal> statements, they are
+        queued and performed in sequence, concurrently with the
+        <literal role="stmt">SELECT</literal> statements. The results of
+        a concurrent <literal role="stmt">INSERT</literal> may not be
+        visible immediately.
+      </para>
+
+      <para>
+        The <literal role="sysvar">concurrent_insert</literal> system
+        variable can be set to modify the concurrent-insert processing.
+        By default, the variable is set to 1 and concurrent inserts are
+        handled as just described. If
+        <literal role="sysvar">concurrent_insert</literal> is set to 0,
+        concurrent inserts are disabled. If the variable is set to 2,
+        concurrent inserts at the end of the table are allowed even for
+        tables that have deleted rows. See also the description of the
+        <link linkend="sysvar_concurrent_insert"><literal role="sysvar">concurrent_insert</literal></link>
+        system variable.
+      </para>
+
+      <para>
+        Under circumstances where concurrent inserts can be used, there
+        is seldom any need to use the <literal>DELAYED</literal>
+        modifier for <literal role="stmt">INSERT</literal> statements.
+        See <xref linkend="insert-delayed"/>.
+      </para>
+
+      <para>
+        If you are using the binary log, concurrent inserts are
+        converted to normal inserts for <literal>CREATE ...
+        SELECT</literal> or
+        <literal role="stmt" condition="insert-select">INSERT ...
+        SELECT</literal> statements. This is done to ensure that you can
+        re-create an exact copy of your tables by applying the log
+        during a backup operation. See <xref linkend="binary-log"/>. In
+        addition, for those statements a read lock is placed on the
+        selected-from table such that inserts into that table are
+        blocked. The effect is that concurrent inserts for that table
+        must wait as well.
+      </para>
+
+      <para>
+        With <literal role="stmt" condition="load-data">LOAD DATA
+        INFILE</literal>, if you specify <literal>CONCURRENT</literal>
+        with a <literal>MyISAM</literal> table that satisfies the
+        condition for concurrent inserts (that is, it contains no free
+        blocks in the middle), other sessions can retrieve data from the
+        table while <literal role="stmt">LOAD DATA</literal> is
+        executing. Use of the <literal>CONCURRENT</literal> option
+        affects the performance of <literal role="stmt">LOAD
+        DATA</literal> a bit, even if no other session is using the
+        table at the same time.
+      </para>
+
+      <para>
+        If you specify <literal>HIGH_PRIORITY</literal>, it overrides
+        the effect of the
+        <option role="mysqld">--low-priority-updates</option> option if
+        the server was started with that option. It also causes
+        concurrent inserts not to be used.
+      </para>
+
+      <para>
+        For <literal role="stmt" condition="lock-tables">LOCK
+        TABLE</literal>, the difference between <literal>READ
+        LOCAL</literal> and <literal>READ</literal> is that
+        <literal>READ LOCAL</literal> permits nonconflicting
+        <literal role="stmt">INSERT</literal> statements (concurrent
+        inserts) to execute while the lock is held. However, this cannot
+        be used if you are going to manipulate the database using
+        processes external to the server while you hold the lock.
+      </para>
+
+    </section>
+
+    <section id="external-locking">
+
+      <title>External Locking</title>
+
+      <indexterm>
+        <primary>external locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>external</secondary>
+      </indexterm>
+
+      <para>
+        External locking is the use of file system locking to manage
+        contention for database tables by multiple processes. External
+        locking is used in situations where a single process such as the
+        MySQL server cannot be assumed to be the only process that
+        requires access to tables. Here are some examples:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            If you run multiple servers that use the same database
+            directory (not recommended), each server must have external
+            locking enabled.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you use <command>myisamchk</command> to perform table
+            maintenance operations on <literal>MyISAM</literal> tables,
+            you must either ensure that the server is not running, or
+            that the server has external locking enabled so that it
+            locks table files as necessary to coordinate with
+            <command>myisamchk</command> for access to the tables. The
+            same is true for use of <command>myisampack</command> to
+            pack <literal>MyISAM</literal> tables.
+          </para>
+
+          <para>
+            If the server is run with external locking enabled, you can
+            use <command>myisamchk</command> at any time for read
+            operations such a checking tables. In this case, if the
+            server tries to update a table that
+            <command>myisamchk</command> is using, the server will wait
+            for <command>myisamchk</command> to finish before it
+            continues.
+          </para>
+
+          <para>
+            If you use <command>myisamchk</command> for write operations
+            such as repairing or optimizing tables, or if you use
+            <command>myisampack</command> to pack tables, you
+            <emphasis>must</emphasis> always ensure that the
+            <command>mysqld</command> server is not using the table. If
+            you don't stop <command>mysqld</command>, you should at
+            least do a <command>mysqladmin flush-tables</command> before
+            you run <command>myisamchk</command>. Your tables
+            <emphasis>may become corrupted</emphasis> if the server and
+            <command>myisamchk</command> access the tables
+            simultaneously.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        With external locking in effect, each process that requires
+        access to a table acquires a file system lock for the table
+        files before proceeding to access the table. If all necessary
+        locks cannot be acquired, the process is blocked from accessing
+        the table until the locks can be obtained (after the process
+        that currently holds the locks releases them).
+      </para>
+
+      <para>
+        External locking affects server performance because the server
+        must sometimes wait for other processes before it can access
+        tables.
+      </para>
+
+      <para>
+        External locking is unnecessary if you run a single server to
+        access a given data directory (which is the usual case) and if
+        no other programs such as <command>myisamchk</command> need to
+        modify tables while the server is running. If you only
+        <emphasis>read</emphasis> tables with other programs, external
+        locking is not required, although <command>myisamchk</command>
+        might report warnings if the server changes tables while
+        <command>myisamchk</command> is reading them.
+      </para>
+
+      <para>
+        With external locking disabled, to use
+        <command>myisamchk</command>, you must either stop the server
+        while <command>myisamchk</command> executes or else lock and
+        flush the tables before running <command>myisamchk</command>.
+        (See <xref linkend="system-optimization"/>.) To avoid this
+        requirement, use the <literal role="stmt">CHECK TABLE</literal>
+        and <literal role="stmt">REPAIR TABLE</literal> statements to
+        check and repair <literal>MyISAM</literal> tables.
+      </para>
+
+      <para>
+        For <command>mysqld</command>, external locking is controlled by
+        the value of the
+        <literal role="sysvar">skip_external_locking</literal> system
+        variable. When this variable is enabled, external locking is
+        disabled, and vice versa. From MySQL 4.0 on, external locking is
+        disabled by default. Before MySQL 4.0, external locking is
+        enabled by default on Linux or when MySQL is configured to use
+        MIT-pthreads.
+      </para>
+
+      <para>
+        Use of external locking can be controlled at server startup by
+        using the <option role="mysqld">--external-locking</option> or
+        <option role="mysqld">--skip-external-locking</option> option.
+      </para>
+
+      <para>
+        If you do use external locking option to enable updates to
+        <literal>MyISAM</literal> tables from many MySQL processes, you
+        must ensure that the following conditions are satisfied:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            You should not use the query cache for queries that use
+            tables that are updated by another process.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            You should not start the server with the
+            <option role="mysqld">--delay-key-write=ALL</option> option
+            or use the <literal>DELAY_KEY_WRITE=1</literal> table option
+            for any shared tables. Otherwise, index corruption can
+            occur.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        The easiest way to satisfy these conditions is to always use
+        <option role="mysqld">--external-locking</option> together with
+        <option role="mysqld">--delay-key-write=OFF</option> and
+        <option role="sysvar">--query-cache-size=0</option>. (This is
+        not done by default because in many setups it is useful to have
+        a mixture of the preceding options.)
+      </para>
+
+    </section>
+
+  </section>
+
+  <section id="optimizing-database-structure">
+
+    <title>Optimizing Database Structure</title>
+
+    <section id="data-size">
+
+      <title>Make Your Data as Small as Possible</title>
+
+      <indexterm>
+        <primary>data</primary>
+        <secondary>size</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>reducing</primary>
+        <secondary>data size</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>storage space</primary>
+        <secondary>minimizing</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>tables</primary>
+        <secondary>improving performance</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>performance</primary>
+        <secondary>improving</secondary>
+      </indexterm>
+
+      <para>
+        One of the most basic optimizations is to design your tables to
+        take as little space on the disk as possible. This can result in
+        huge improvements because disk reads are faster, and smaller
+        tables normally require less main memory while their contents
+        are being actively processed during query execution. Indexing
+        also is a lesser resource burden if done on smaller columns.
+      </para>
+
+      <para>
+        MySQL supports many different storage engines (table types) and
+        row formats. For each table, you can decide which storage and
+        indexing method to use. Choosing the proper table format for
+        your application may give you a big performance gain. See
+        <xref linkend="storage-engines"/>.
+      </para>
+
+      <para>
+        You can get better performance for a table and minimize storage
+        space by using the techniques listed here:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Use the most efficient (smallest) data types possible. MySQL
+            has many specialized types that save disk space and memory.
+            For example, use the smaller integer types if possible to
+            get smaller tables. <literal role="type">MEDIUMINT</literal>
+            is often a better choice than
+            <literal role="type">INT</literal> because a
+            <literal role="type">MEDIUMINT</literal> column uses 25%
+            less space.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Declare columns to be <literal>NOT NULL</literal> if
+            possible. It makes everything faster and you save one bit
+            per column. If you really need <literal>NULL</literal> in
+            your application, you should definitely use it. Just avoid
+            having it on all columns by default.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            For <literal>MyISAM</literal> tables, if you do not have any
+            variable-length columns
+            (<literal role="type">VARCHAR</literal>,
+            <literal role="type">TEXT</literal>, or
+            <literal role="type">BLOB</literal> columns), a fixed-size
+            row format is used. This is faster but unfortunately may
+            waste some space. See
+            <xref linkend="myisam-table-formats"/>. You can hint that
+            you want to have fixed length rows even if you have
+            <literal role="type">VARCHAR</literal> columns with the
+            <literal role="stmt">CREATE TABLE</literal> option
+            <literal>ROW_FORMAT=FIXED</literal>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            <literal>InnoDB</literal> tables use a compact storage
+            format. In versions of MySQL earlier than 5.0.3,
+            <literal>InnoDB</literal> rows contain some redundant
+            information, such as the number of columns and the length of
+            each column, even for fixed-size columns. By default, tables
+            are created in the compact format
+            (<literal>ROW_FORMAT=COMPACT</literal>). If you wish to
+            downgrade to older versions of MySQL, you can request the
+            old format with <literal>ROW_FORMAT=REDUNDANT</literal>.
+          </para>
+
+          <para>
+            The presence of the compact row format decreases row storage
+            space by about 20% at the cost of increasing CPU use for
+            some operations. If your workload is a typical one that is
+            limited by cache hit rates and disk speed it is likely to be
+            faster. If it is a rare case that is limited by CPU speed,
+            it might be slower.
+          </para>
+
+          <para>
+            The compact <literal>InnoDB</literal> format also changes
+            how <literal role="type">CHAR</literal> columns containing
+            UTF-8 data are stored. With
+            <literal>ROW_FORMAT=REDUNDANT</literal>, a UTF-8
+            <literal>CHAR(<replaceable>N</replaceable>)</literal>
+            occupies 3 &times; <replaceable>N</replaceable> bytes, given
+            that the maximum length of a UTF-8 encoded character is
+            three bytes. Many languages can be written primarily using
+            single-byte UTF-8 characters, so a fixed storage length
+            often wastes space. With
+            <literal>ROW_FORMAT=COMPACT</literal> format,
+            <literal>InnoDB</literal> allocates a variable amount of
+            storage in the range from <replaceable>N</replaceable> to 3
+            &times; <replaceable>N</replaceable> bytes for these columns
+            by stripping trailing spaces if necessary. The minimum
+            storage length is kept as <replaceable>N</replaceable> bytes
+            to facilitate in-place updates in typical cases.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            The primary index of a table should be as short as possible.
+            This makes identification of each row easy and efficient.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Create only the indexes that you really need. Indexes are
+            good for retrieval but bad when you need to store data
+            quickly. If you access a table mostly by searching on a
+            combination of columns, create an index on them. The first
+            part of the index should be the column most used. If you
+            <emphasis>always</emphasis> use many columns when selecting
+            from the table, the first column in the index should be the
+            one with the most duplicates to obtain better compression of
+            the index.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If it is very likely that a string column has a unique
+            prefix on the first number of characters, it is better to
+            index only this prefix, using MySQL's support for creating
+            an index on the leftmost part of the column (see
+            <xref linkend="create-index"/>). Shorter indexes are faster,
+            not only because they require less disk space, but because
+            they also give you more hits in the index cache, and thus
+            fewer disk seeks. See <xref linkend="server-parameters"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            In some circumstances, it can be beneficial to split into
+            two a table that is scanned very often. This is especially
+            true if it is a dynamic-format table and it is possible to
+            use a smaller static format table that can be used to find
+            the relevant rows when scanning the table.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+    </section>
+
     <section id="table-cache">
 
       <title>How MySQL Opens and Closes Tables</title>


Modified: trunk/refman-5.1/renamed-nodes.txt
===================================================================
--- trunk/refman-5.1/renamed-nodes.txt	2010-07-14 15:11:37 UTC (rev 21727)
+++ trunk/refman-5.1/renamed-nodes.txt	2010-07-14 15:35:58 UTC (rev 21728)
Changed blocks: 1, Lines Added: 1, Lines Deleted: 0; 660 bytes

@@ -45,6 +45,7 @@
 events-limitations-restrictions stored-program-restrictions 2009-09-19
 german-character-set charset-we-sets 2010-08-08
 group-by-hidden-fields group-by-hidden-columns 2010-01-01
+indexes column-indexes 2011-07-14
 innodb-and-autocommit innodb-transaction-model 2009-11-24
 innodb-consistent-read-example innodb-consistent-read 2010-03-10
 innodb-general-monitor innodb-monitors 2010-11-05


Modified: trunk/refman-5.1/sql-syntax-data-definition.xml
===================================================================
--- trunk/refman-5.1/sql-syntax-data-definition.xml	2010-07-14 15:11:37 UTC (rev 21727)
+++ trunk/refman-5.1/sql-syntax-data-definition.xml	2010-07-14 15:35:58 UTC (rev 21728)
Changed blocks: 1, Lines Added: 1, Lines Deleted: 1; 663 bytes

@@ -5939,7 +5939,7 @@
           <literal role="type">VARBINARY</literal>, and
           <literal role="type">BLOB</literal> columns. Indexing only a
           prefix of column values like this can make the index file much
-          smaller. See <xref linkend="indexes"/>.
+          smaller. See <xref linkend="column-indexes"/>.
         </para>
 
         <indexterm>


Modified: trunk/refman-5.5/data-types.xml
===================================================================
--- trunk/refman-5.5/data-types.xml	2010-07-14 15:11:37 UTC (rev 21727)
+++ trunk/refman-5.5/data-types.xml	2010-07-14 15:35:58 UTC (rev 21728)
Changed blocks: 1, Lines Added: 1, Lines Deleted: 1; 594 bytes

@@ -4643,7 +4643,7 @@
             specify an index prefix length. For
             <literal role="type">CHAR</literal> and
             <literal role="type">VARCHAR</literal>, a prefix length is
-            optional. See <xref linkend="indexes"/>.
+            optional. See <xref linkend="column-indexes"/>.
           </para>
         </listitem>
 


Modified: trunk/refman-5.5/optimization.xml
===================================================================
--- trunk/refman-5.5/optimization.xml	2010-07-14 15:11:37 UTC (rev 21727)
+++ trunk/refman-5.5/optimization.xml	2010-07-14 15:35:58 UTC (rev 21728)
Changed blocks: 3, Lines Added: 1194, Lines Deleted: 1188; 88249 bytes

@@ -8761,1196 +8761,12 @@
 
   </section>
 
-  <section id="locking-issues">
+  <section id="optimization-indexes">
 
-    <title>Locking Issues</title>
+    <title>Optimization and Indexes</title>
 
-    <para>
-      MySQL manages contention for table contents using locking:
-    </para>
+    <section id="column-indexes">
 
-    <itemizedlist>
-
-      <listitem>
-        <para>
-          Internal locking is performed within the MySQL server itself
-          to manage contention for table contents by multiple threads.
-          This type of locking is internal because it is performed
-          entirely by the server and involves no other programs. See
-          <xref linkend="internal-locking"/>.
-        </para>
-      </listitem>
-
-      <listitem>
-        <para>
-          External locking occurs when the server and other programs
-          lock table files to coordinate among themselves which program
-          can access the tables at which time. See
-          <xref linkend="external-locking"/>.
-        </para>
-      </listitem>
-
-    </itemizedlist>
-
-    <section id="internal-locking">
-
-      <title>Internal Locking Methods</title>
-
-      <indexterm>
-        <primary>internal locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>internal</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking methods</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>methods</primary>
-        <secondary>locking</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>row-level locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>table-level locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>row-level</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>table-level</secondary>
-      </indexterm>
-
-      <para>
-        This section discusses internal locking; that is, locking
-        performed within the MySQL server itself to manage contention
-        for table contents by multiple sessions. This type of locking is
-        internal because it is performed entirely by the server and
-        involves no other programs. External locking occurs when the
-        server and other programs lock table files to coordinate among
-        themselves which program can access the tables at which time.
-        See <xref linkend="external-locking"/>.
-      </para>
-
-      <para>
-        MySQL uses table-level locking for <literal>MyISAM</literal>,
-        <literal>MEMORY</literal>, and <literal>MERGE</literal> tables,
-        and row-level locking for <literal>InnoDB</literal> tables.
-      </para>
-
-      <para>
-        In many cases, you can make an educated guess about which
-        locking type is best for an application, but generally it is
-        difficult to say that a given lock type is better than another.
-        Everything depends on the application and different parts of an
-        application may require different lock types.
-      </para>
-
-      <para>
-        To decide whether you want to use a storage engine with
-        row-level locking, you should look at what your application does
-        and what mix of select and update statements it uses. For
-        example, most Web applications perform many selects, relatively
-        few deletes, updates based mainly on key values, and inserts
-        into a few specific tables. The base MySQL
-        <literal>MyISAM</literal> setup is very well tuned for this.
-      </para>
-
-      <formalpara role="mnmas">
-
-        <title>MySQL Enterprise</title>
-
-        <para>
-          The MySQL Enterprise Monitor provides expert advice on when to
-          use table-level locking and when to use row-level locking. To
-          subscribe, see &base-url-enterprise;advisors.html.
-        </para>
-
-      </formalpara>
-
-      <para>
-        Table locking in MySQL is deadlock-free for storage engines that
-        use table-level locking. Deadlock avoidance is managed by always
-        requesting all needed locks at once at the beginning of a query
-        and always locking the tables in the same order.
-      </para>
-
-      <para>
-        MySQL grants table write locks as follows:
-      </para>
-
-      <orderedlist>
-
-        <listitem>
-          <para>
-            If there are no locks on the table, put a write lock on it.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Otherwise, put the lock request in the write lock queue.
-          </para>
-        </listitem>
-
-      </orderedlist>
-
-      <para>
-        MySQL grants table read locks as follows:
-      </para>
-
-      <orderedlist>
-
-        <listitem>
-          <para>
-            If there are no write locks on the table, put a read lock on
-            it.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Otherwise, put the lock request in the read lock queue.
-          </para>
-        </listitem>
-
-      </orderedlist>
-
-      <para>
-        Table updates are given higher priority than table retrievals.
-        Therefore, when a lock is released, the lock is made available
-        to the requests in the write lock queue and then to the requests
-        in the read lock queue. This ensures that updates to a table are
-        not <quote>starved</quote> even if there is heavy
-        <literal role="stmt">SELECT</literal> activity for the table.
-        However, if you have many updates for a table,
-        <literal role="stmt">SELECT</literal> statements wait until
-        there are no more updates.
-      </para>
-
-      <para>
-        For information on altering the priority of reads and writes,
-        see <xref linkend="table-locking"/>.
-      </para>
-
-      <para>
-        You can analyze the table lock contention on your system by
-        checking the
-        <literal role="statvar">Table_locks_immediate</literal> and
-        <literal role="statvar">Table_locks_waited</literal> status
-        variables, which indicate the number of times that requests for
-        table locks could be granted immediately and the number that had
-        to wait, respectively:
-      </para>
-
-<programlisting>
-mysql&gt; <userinput>SHOW STATUS LIKE 'Table%';</userinput>
-+-----------------------+---------+
-| Variable_name         | Value   |
-+-----------------------+---------+
-| Table_locks_immediate | 1151552 |
-| Table_locks_waited    | 15324   |
-+-----------------------+---------+
-</programlisting>
-
-      <indexterm>
-        <primary>concurrent inserts</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>inserts</primary>
-        <secondary>concurrent</secondary>
-      </indexterm>
-
-      <para>
-        The <literal>MyISAM</literal> storage engine supports concurrent
-        inserts to reduce contention between readers and writers for a
-        given table: If a <literal>MyISAM</literal> table has no free
-        blocks in the middle of the data file, rows are always inserted
-        at the end of the data file. In this case, you can freely mix
-        concurrent <literal role="stmt">INSERT</literal> and
-        <literal role="stmt">SELECT</literal> statements for a
-        <literal>MyISAM</literal> table without locks. That is, you can
-        insert rows into a <literal>MyISAM</literal> table at the same
-        time other clients are reading from it. Holes can result from
-        rows having been deleted from or updated in the middle of the
-        table. If there are holes, concurrent inserts are disabled but
-        are enabled again automatically when all holes have been filled
-        with new data.. This behavior is altered by the
-        <literal role="sysvar">concurrent_insert</literal> system
-        variable. See <xref linkend="concurrent-inserts"/>.
-      </para>
-
-      <para>
-        If you acquire a table lock explicitly with
-        <literal role="stmt">LOCK TABLES</literal>, you can request a
-        <literal>READ LOCAL</literal> lock rather than a
-        <literal>READ</literal> lock to enable other sessions to perform
-        concurrent inserts while you have the table locked.
-      </para>
-
-      <para>
-        To perform many <literal role="stmt">INSERT</literal> and
-        <literal role="stmt">SELECT</literal> operations on a table
-        <literal>real_table</literal> when concurrent inserts are not
-        possible, you can insert rows into a temporary table
-        <literal>temp_table</literal> and update the real table with the
-        rows from the temporary table periodically. This can be done
-        with the following code:
-      </para>
-
-<programlisting>
-mysql&gt; <userinput>LOCK TABLES real_table WRITE, temp_table WRITE;</userinput>
-mysql&gt; <userinput>INSERT INTO real_table SELECT * FROM temp_table;</userinput>
-mysql&gt; <userinput>DELETE FROM temp_table;</userinput>
-mysql&gt; <userinput>UNLOCK TABLES;</userinput>
-</programlisting>
-
-      <para>
-        <literal>InnoDB</literal> uses row locks. Deadlocks are possible
-        for <literal>InnoDB</literal> because it automatically acquires
-        locks during the processing of SQL statements, not at the start
-        of the transaction.
-      </para>
-
-      <para>
-        Advantages of row-level locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Fewer lock conflicts when different sessions access
-            different rows
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Fewer changes for rollbacks
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Possible to lock a single row for a long time
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Disadvantages of row-level locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Requires more memory than table-level locks
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Slower than table-level locks when used on a large part of
-            the table because you must acquire many more locks
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Slower than other locks if you often do <literal>GROUP
-            BY</literal> operations on a large part of the data or if
-            you must scan the entire table frequently
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Generally, table locks are superior to row-level locks in the
-        following cases:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Most statements for the table are reads
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Statements for the table are a mix of reads and writes,
-            where writes are updates or deletes for a single row that
-            can be fetched with one key read:
-          </para>
-
-<programlisting>
-UPDATE <replaceable>tbl_name</replaceable> SET <replaceable>column</replaceable>=<replaceable>value</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
-DELETE FROM <replaceable>tbl_name</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
-</programlisting>
-        </listitem>
-
-        <listitem>
-          <para>
-            <literal role="stmt">SELECT</literal> combined with
-            concurrent <literal role="stmt">INSERT</literal> statements,
-            and very few <literal role="stmt">UPDATE</literal> or
-            <literal role="stmt">DELETE</literal> statements
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Many scans or <literal>GROUP BY</literal> operations on the
-            entire table without any writers
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        With higher-level locks, you can more easily tune applications
-        by supporting locks of different types, because the lock
-        overhead is less than for row-level locks.
-      </para>
-
-      <para>
-        Options other than row-level locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Versioning (such as that used in MySQL for concurrent
-            inserts) where it is possible to have one writer at the same
-            time as many readers. This means that the database or table
-            supports different views for the data depending on when
-            access begins. Other common terms for this are <quote>time
-            travel,</quote> <quote>copy on write,</quote> or <quote>copy
-            on demand.</quote>
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Copy on demand is in many cases superior to row-level
-            locking. However, in the worst case, it can use much more
-            memory than using normal locks.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Instead of using row-level locks, you can employ
-            application-level locks, such as those provided by
-            <literal role="func">GET_LOCK()</literal> and
-            <literal role="func">RELEASE_LOCK()</literal> in MySQL.
-            These are advisory locks, so they work only with
-            applications that cooperate with each other. See
-            <xref linkend="miscellaneous-functions"/>.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-    </section>
-
-    <section id="table-locking">
-
-      <title>Table Locking Issues</title>
-
-      <indexterm>
-        <primary>problems</primary>
-        <secondary>table locking</secondary>
-      </indexterm>
-
-      <para>
-        To achieve a very high lock speed, MySQL uses table locking
-        (instead of page, row, or column locking) for all storage
-        engines except <literal>InnoDB</literal>.
-      </para>
-
-      <para>
-        For <literal>InnoDB</literal> tables, MySQL uses table locking
-        only if you explicitly lock the table with
-        <literal role="stmt">LOCK TABLES</literal>. For this storage
-        engine, avoid using <literal role="stmt">LOCK TABLES</literal>
-        at all, because <literal>InnoDB</literal> uses automatic
-        row-level locking to ensure transaction isolation.
-      </para>
-
-      <para>
-        For large tables, table locking is often better than row
-        locking, but there are some disadvantages:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Table locking enables many sessions to read from a table at
-            the same time, but if a session wants to write to a table,
-            it must first get exclusive access. During the update, all
-            other sessions that want to access this particular table
-            must wait until the update is done.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Table locking causes problems in cases such as when a
-            session is waiting because the disk is full and free space
-            needs to become available before the session can proceed. In
-            this case, all sessions that want to access the problem
-            table are also put in a waiting state until more disk space
-            is made available.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Table locking is also disadvantageous under the following
-        scenario:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            A session issues a <literal role="stmt">SELECT</literal>
-            that takes a long time to run.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Another session then issues an
-            <literal role="stmt">UPDATE</literal> on the same table.
-            This session waits until the
-            <literal role="stmt">SELECT</literal> is finished.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Another session issues another
-            <literal role="stmt">SELECT</literal> statement on the same
-            table. Because <literal role="stmt">UPDATE</literal> has
-            higher priority than <literal role="stmt">SELECT</literal>,
-            this <literal role="stmt">SELECT</literal> waits for the
-            <literal role="stmt">UPDATE</literal> to finish,
-            <emphasis>after</emphasis> waiting for the first
-            <literal role="stmt">SELECT</literal> to finish.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        The following items describe some ways to avoid or reduce
-        contention caused by table locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Try to get the <literal role="stmt">SELECT</literal>
-            statements to run faster so that they lock tables for a
-            shorter time. You might have to create some summary tables
-            to do this.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Start <command>mysqld</command> with
-            <option role="mysqld">--low-priority-updates</option>. For
-            storage engines that use only table-level locking (such as
-            <literal>MyISAM</literal>, <literal>MEMORY</literal>, and
-            <literal>MERGE</literal>), this gives all statements that
-            update (modify) a table lower priority than
-            <literal role="stmt">SELECT</literal> statements. In this
-            case, the second <literal role="stmt">SELECT</literal>
-            statement in the preceding scenario would execute before the
-            <literal role="stmt">UPDATE</literal> statement, and would
-            not need to wait for the first
-            <literal role="stmt">SELECT</literal> to finish.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            To specify that all updates issued in a specific connection
-            should be done with low priority, set the
-            <literal role="sysvar">low_priority_updates</literal> server
-            system variable equal to 1.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            To give a specific <literal role="stmt">INSERT</literal>,
-            <literal role="stmt">UPDATE</literal>, or
-            <literal role="stmt">DELETE</literal> statement lower
-            priority, use the <literal>LOW_PRIORITY</literal> attribute.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            To give a specific <literal role="stmt">SELECT</literal>
-            statement higher priority, use the
-            <literal>HIGH_PRIORITY</literal> attribute. See
-            <xref linkend="select"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Start <command>mysqld</command> with a low value for the
-            <literal role="sysvar">max_write_lock_count</literal> system
-            variable to force MySQL to temporarily elevate the priority
-            of all <literal role="stmt">SELECT</literal> statements that
-            are waiting for a table after a specific number of inserts
-            to the table occur. This permits <literal>READ</literal>
-            locks after a certain number of <literal>WRITE</literal>
-            locks.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you have problems with
-            <literal role="stmt">INSERT</literal> combined with
-            <literal role="stmt">SELECT</literal>, consider switching to
-            <literal>MyISAM</literal> tables, which support concurrent
-            <literal role="stmt">SELECT</literal> and
-            <literal role="stmt">INSERT</literal> statements. (See
-            <xref linkend="concurrent-inserts"/>.)
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you mix inserts and deletes on the same table,
-            <literal role="stmt">INSERT DELAYED</literal> may be of
-            great help. See <xref linkend="insert-delayed"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you have problems with mixed
-            <literal role="stmt">SELECT</literal> and
-            <literal role="stmt">DELETE</literal> statements, the
-            <literal>LIMIT</literal> option to
-            <literal role="stmt">DELETE</literal> may help. See
-            <xref linkend="delete"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Using <literal>SQL_BUFFER_RESULT</literal> with
-            <literal role="stmt">SELECT</literal> statements can help to
-            make the duration of table locks shorter. See
-            <xref linkend="select"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            You could change the locking code in
-            <filename>mysys/thr_lock.c</filename> to use a single queue.
-            In this case, write locks and read locks would have the same
-            priority, which might help some applications.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Here are some tips concerning table locks in MySQL:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Concurrent users are not a problem if you do not mix updates
-            with selects that need to examine many rows in the same
-            table.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            You can use <literal role="stmt">LOCK TABLES</literal> to
-            increase speed, because many updates within a single lock is
-            much faster than updating without locks. Splitting table
-            contents into separate tables may also help.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you encounter speed problems with table locks in MySQL,
-            you may be able to improve performance by converting some of
-            your tables to <literal>InnoDB</literal>. See
-            <xref linkend="innodb"/>.
-          </para>
-
-          <formalpara role="mnmas">
-
-            <title>MySQL Enterprise</title>
-
-            <para>
-              Lock contention can seriously degrade performance. The
-              MySQL Enterprise Monitor provides expert advice on
-              avoiding this problem. To subscribe, see
-              &base-url-enterprise;advisors.html.
-            </para>
-
-          </formalpara>
-        </listitem>
-
-      </itemizedlist>
-
-    </section>
-
-    <section id="concurrent-inserts">
-
-      <title>Concurrent Inserts</title>
-
-      <indexterm>
-        <primary>concurrent inserts</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>inserts</primary>
-        <secondary>concurrent</secondary>
-      </indexterm>
-
-      <para>
-        The <literal>MyISAM</literal> storage engine supports concurrent
-        inserts to reduce contention between readers and writers for a
-        given table: If a <literal>MyISAM</literal> table has no holes
-        in the data file (deleted rows in the middle), an
-        <literal role="stmt">INSERT</literal> statement can be executed
-        to add rows to the end of the table at the same time that
-        <literal role="stmt">SELECT</literal> statements are reading
-        rows from the table. If there are multiple
-        <literal role="stmt">INSERT</literal> statements, they are
-        queued and performed in sequence, concurrently with the
-        <literal role="stmt">SELECT</literal> statements. The results of
-        a concurrent <literal role="stmt">INSERT</literal> may not be
-        visible immediately.
-      </para>
-
-      <para>
-        The <literal role="sysvar">concurrent_insert</literal> system
-        variable can be set to modify the concurrent-insert processing.
-        By default, the variable is set to <literal>AUTO</literal> (or
-        1) and concurrent inserts are handled as just described. If
-        <literal role="sysvar">concurrent_insert</literal> is set to
-        <literal>NEVER</literal> (or 0), concurrent inserts are
-        disabled. If the variable is set to <literal>ALWAYS</literal>
-        (or 2), concurrent inserts at the end of the table are allowed
-        even for tables that have deleted rows. See also the description
-        of the
-        <link linkend="sysvar_concurrent_insert"><literal role="sysvar">concurrent_insert</literal></link>
-        system variable.
-      </para>
-
-      <para>
-        Under circumstances where concurrent inserts can be used, there
-        is seldom any need to use the <literal>DELAYED</literal>
-        modifier for <literal role="stmt">INSERT</literal> statements.
-        See <xref linkend="insert-delayed"/>.
-      </para>
-
-      <para>
-        If you are using the binary log, concurrent inserts are
-        converted to normal inserts for <literal>CREATE ...
-        SELECT</literal> or
-        <literal role="stmt" condition="insert-select">INSERT ...
-        SELECT</literal> statements. This is done to ensure that you can
-        re-create an exact copy of your tables by applying the log
-        during a backup operation. See <xref linkend="binary-log"/>. In
-        addition, for those statements a read lock is placed on the
-        selected-from table such that inserts into that table are
-        blocked. The effect is that concurrent inserts for that table
-        must wait as well.
-      </para>
-
-      <para>
-        With <literal role="stmt" condition="load-data">LOAD DATA
-        INFILE</literal>, if you specify <literal>CONCURRENT</literal>
-        with a <literal>MyISAM</literal> table that satisfies the
-        condition for concurrent inserts (that is, it contains no free
-        blocks in the middle), other sessions can retrieve data from the
-        table while <literal role="stmt">LOAD DATA</literal> is
-        executing. Use of the <literal>CONCURRENT</literal> option
-        affects the performance of <literal role="stmt">LOAD
-        DATA</literal> a bit, even if no other session is using the
-        table at the same time.
-      </para>
-
-      <para>
-        If you specify <literal>HIGH_PRIORITY</literal>, it overrides
-        the effect of the
-        <option role="mysqld">--low-priority-updates</option> option if
-        the server was started with that option. It also causes
-        concurrent inserts not to be used.
-      </para>
-
-      <para>
-        For <literal role="stmt" condition="lock-tables">LOCK
-        TABLE</literal>, the difference between <literal>READ
-        LOCAL</literal> and <literal>READ</literal> is that
-        <literal>READ LOCAL</literal> permits nonconflicting
-        <literal role="stmt">INSERT</literal> statements (concurrent
-        inserts) to execute while the lock is held. However, this cannot
-        be used if you are going to manipulate the database using
-        processes external to the server while you hold the lock.
-      </para>
-
-    </section>
-
-    <section id="metadata-locking">
-
-      <title>Metadata Locking Within Transactions</title>
-
-      <indexterm>
-        <primary>metadata locking</primary>
-        <secondary>transactions</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>transactions</primary>
-        <secondary>metadata locking</secondary>
-      </indexterm>
-
-      <para>
-        To ensure transaction serializability, the server must not allow
-        one session to perform a data definition language (DDL)
-        statement on a table that is used in an uncompleted transaction
-        in another session.
-      </para>
-
-      <para>
-        As of MySQL 5.5.3, the server achieves this by acquiring
-        metadata locks on tables used within a transaction and deferring
-        release of those locks until the transaction ends. A metadata
-        lock on a table prevents changes to the table's structure. This
-        locking approach has the implication that a table that is being
-        used by a transaction within one session cannot be used in DDL
-        statements by other sessions until the transaction ends. For
-        example, if a table <literal>t1</literal> is in use by a
-        transaction, another session that attempts to execute
-        <literal role="stmt" condition="drop-table">DROP TABLE
-        t1</literal> will block until the transaction ends.
-      </para>
-
-      <para>
-        If the server acquires metadata locks for a statement that is
-        syntactically valid but fails during execution, it does not
-        release the locks early. Lock release is still deferred to the
-        end of the transaction because the failed statement is written
-        to the binary log and the locks protect log consistency.
-      </para>
-
-      <para>
-        Metadata locks acquired during a
-        <literal role="stmt">PREPARE</literal> statement are released
-        once the statement has been prepared, even if preparation occurs
-        within a multiple-statement transaction.
-      </para>
-
-      <para>
-        Before MySQL 5.5.3, when a transaction acquired a metadata lock
-        for a table used within a statement, it released the lock at the
-        end of the statement. This approach had the disadvantage that if
-        a DDL statement occurred for a table that was being used by
-        another session in an active transaction, statements could be
-        written to the binary log in the wrong order.
-      </para>
-
-    </section>
-
-    <section id="external-locking">
-
-      <title>External Locking</title>
-
-      <indexterm>
-        <primary>external locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>external</secondary>
-      </indexterm>
-
-      <para>
-        External locking is the use of file system locking to manage
-        contention for database tables by multiple processes. External
-        locking is used in situations where a single process such as the
-        MySQL server cannot be assumed to be the only process that
-        requires access to tables. Here are some examples:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            If you run multiple servers that use the same database
-            directory (not recommended), each server must have external
-            locking enabled.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you use <command>myisamchk</command> to perform table
-            maintenance operations on <literal>MyISAM</literal> tables,
-            you must either ensure that the server is not running, or
-            that the server has external locking enabled so that it
-            locks table files as necessary to coordinate with
-            <command>myisamchk</command> for access to the tables. The
-            same is true for use of <command>myisampack</command> to
-            pack <literal>MyISAM</literal> tables.
-          </para>
-
-          <para>
-            If the server is run with external locking enabled, you can
-            use <command>myisamchk</command> at any time for read
-            operations such a checking tables. In this case, if the
-            server tries to update a table that
-            <command>myisamchk</command> is using, the server will wait
-            for <command>myisamchk</command> to finish before it
-            continues.
-          </para>
-
-          <para>
-            If you use <command>myisamchk</command> for write operations
-            such as repairing or optimizing tables, or if you use
-            <command>myisampack</command> to pack tables, you
-            <emphasis>must</emphasis> always ensure that the
-            <command>mysqld</command> server is not using the table. If
-            you don't stop <command>mysqld</command>, you should at
-            least do a <command>mysqladmin flush-tables</command> before
-            you run <command>myisamchk</command>. Your tables
-            <emphasis>may become corrupted</emphasis> if the server and
-            <command>myisamchk</command> access the tables
-            simultaneously.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        With external locking in effect, each process that requires
-        access to a table acquires a file system lock for the table
-        files before proceeding to access the table. If all necessary
-        locks cannot be acquired, the process is blocked from accessing
-        the table until the locks can be obtained (after the process
-        that currently holds the locks releases them).
-      </para>
-
-      <para>
-        External locking affects server performance because the server
-        must sometimes wait for other processes before it can access
-        tables.
-      </para>
-
-      <para>
-        External locking is unnecessary if you run a single server to
-        access a given data directory (which is the usual case) and if
-        no other programs such as <command>myisamchk</command> need to
-        modify tables while the server is running. If you only
-        <emphasis>read</emphasis> tables with other programs, external
-        locking is not required, although <command>myisamchk</command>
-        might report warnings if the server changes tables while
-        <command>myisamchk</command> is reading them.
-      </para>
-
-      <para>
-        With external locking disabled, to use
-        <command>myisamchk</command>, you must either stop the server
-        while <command>myisamchk</command> executes or else lock and
-        flush the tables before running <command>myisamchk</command>.
-        (See <xref linkend="system-optimization"/>.) To avoid this
-        requirement, use the <literal role="stmt">CHECK TABLE</literal>
-        and <literal role="stmt">REPAIR TABLE</literal> statements to
-        check and repair <literal>MyISAM</literal> tables.
-      </para>
-
-      <para>
-        For <command>mysqld</command>, external locking is controlled by
-        the value of the
-        <literal role="sysvar">skip_external_locking</literal> system
-        variable. When this variable is enabled, external locking is
-        disabled, and vice versa. From MySQL 4.0 on, external locking is
-        disabled by default. Before MySQL 4.0, external locking is
-        enabled by default on Linux or when MySQL is configured to use
-        MIT-pthreads.
-      </para>
-
-      <para>
-        Use of external locking can be controlled at server startup by
-        using the <option role="mysqld">--external-locking</option> or
-        <option role="mysqld">--skip-external-locking</option> option.
-      </para>
-
-      <para>
-        If you do use external locking option to enable updates to
-        <literal>MyISAM</literal> tables from many MySQL processes, you
-        must ensure that the following conditions are satisfied:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            You should not use the query cache for queries that use
-            tables that are updated by another process.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            You should not start the server with the
-            <option role="mysqld">--delay-key-write=ALL</option> option
-            or use the <literal>DELAY_KEY_WRITE=1</literal> table option
-            for any shared tables. Otherwise, index corruption can
-            occur.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        The easiest way to satisfy these conditions is to always use
-        <option role="mysqld">--external-locking</option> together with
-        <option role="mysqld">--delay-key-write=OFF</option> and
-        <option role="sysvar">--query-cache-size=0</option>. (This is
-        not done by default because in many setups it is useful to have
-        a mixture of the preceding options.)
-      </para>
-
-    </section>
-
-  </section>
-
-  <section id="optimizing-database-structure">
-
-    <title>Optimizing Database Structure</title>
-
-    <section id="data-size">
-
-      <title>Make Your Data as Small as Possible</title>
-
-      <indexterm>
-        <primary>data</primary>
-        <secondary>size</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>reducing</primary>
-        <secondary>data size</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>storage space</primary>
-        <secondary>minimizing</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>tables</primary>
-        <secondary>improving performance</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>performance</primary>
-        <secondary>improving</secondary>
-      </indexterm>
-
-      <para>
-        One of the most basic optimizations is to design your tables to
-        take as little space on the disk as possible. This can result in
-        huge improvements because disk reads are faster, and smaller
-        tables normally require less main memory while their contents
-        are being actively processed during query execution. Indexing
-        also is a lesser resource burden if done on smaller columns.
-      </para>
-
-      <para>
-        MySQL supports many different storage engines (table types) and
-        row formats. For each table, you can decide which storage and
-        indexing method to use. Choosing the proper table format for
-        your application may give you a big performance gain. See
-        <xref linkend="storage-engines"/>.
-      </para>
-
-      <para>
-        You can get better performance for a table and minimize storage
-        space by using the techniques listed here:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Use the most efficient (smallest) data types possible. MySQL
-            has many specialized types that save disk space and memory.
-            For example, use the smaller integer types if possible to
-            get smaller tables. <literal role="type">MEDIUMINT</literal>
-            is often a better choice than
-            <literal role="type">INT</literal> because a
-            <literal role="type">MEDIUMINT</literal> column uses 25%
-            less space.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Declare columns to be <literal>NOT NULL</literal> if
-            possible. It makes everything faster and you save one bit
-            per column. If you really need <literal>NULL</literal> in
-            your application, you should definitely use it. Just avoid
-            having it on all columns by default.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            For <literal>MyISAM</literal> tables, if you do not have any
-            variable-length columns
-            (<literal role="type">VARCHAR</literal>,
-            <literal role="type">TEXT</literal>, or
-            <literal role="type">BLOB</literal> columns), a fixed-size
-            row format is used. This is faster but unfortunately may
-            waste some space. See
-            <xref linkend="myisam-table-formats"/>. You can hint that
-            you want to have fixed length rows even if you have
-            <literal role="type">VARCHAR</literal> columns with the
-            <literal role="stmt">CREATE TABLE</literal> option
-            <literal>ROW_FORMAT=FIXED</literal>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            <literal>InnoDB</literal> tables use a compact storage
-            format. In versions of MySQL earlier than 5.0.3,
-            <literal>InnoDB</literal> rows contain some redundant
-            information, such as the number of columns and the length of
-            each column, even for fixed-size columns. By default, tables
-            are created in the compact format
-            (<literal>ROW_FORMAT=COMPACT</literal>). If you wish to
-            downgrade to older versions of MySQL, you can request the
-            old format with <literal>ROW_FORMAT=REDUNDANT</literal>.
-          </para>
-
-          <para>
-            The presence of the compact row format decreases row storage
-            space by about 20% at the cost of increasing CPU use for
-            some operations. If your workload is a typical one that is
-            limited by cache hit rates and disk speed it is likely to be
-            faster. If it is a rare case that is limited by CPU speed,
-            it might be slower.
-          </para>
-
-          <para>
-            The compact <literal>InnoDB</literal> format also changes
-            how <literal role="type">CHAR</literal> columns containing
-            UTF-8 data are stored. With
-            <literal>ROW_FORMAT=REDUNDANT</literal>, a UTF-8
-            <literal>CHAR(<replaceable>N</replaceable>)</literal>
-            occupies 3 &times; <replaceable>N</replaceable> bytes, given
-            that the maximum length of a UTF-8 encoded character is
-            three bytes. Many languages can be written primarily using
-            single-byte UTF-8 characters, so a fixed storage length
-            often wastes space. With
-            <literal>ROW_FORMAT=COMPACT</literal> format,
-            <literal>InnoDB</literal> allocates a variable amount of
-            storage in the range from <replaceable>N</replaceable> to 3
-            &times; <replaceable>N</replaceable> bytes for these columns
-            by stripping trailing spaces if necessary. The minimum
-            storage length is kept as <replaceable>N</replaceable> bytes
-            to facilitate in-place updates in typical cases.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            The primary index of a table should be as short as possible.
-            This makes identification of each row easy and efficient.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Create only the indexes that you really need. Indexes are
-            good for retrieval but bad when you need to store data
-            quickly. If you access a table mostly by searching on a
-            combination of columns, create an index on them. The first
-            part of the index should be the column most used. If you
-            <emphasis>always</emphasis> use many columns when selecting
-            from the table, the first column in the index should be the
-            one with the most duplicates to obtain better compression of
-            the index.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If it is very likely that a string column has a unique
-            prefix on the first number of characters, it is better to
-            index only this prefix, using MySQL's support for creating
-            an index on the leftmost part of the column (see
-            <xref linkend="create-index"/>). Shorter indexes are faster,
-            not only because they require less disk space, but because
-            they also give you more hits in the index cache, and thus
-            fewer disk seeks. See <xref linkend="server-parameters"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            In some circumstances, it can be beneficial to split into
-            two a table that is scanned very often. This is especially
-            true if it is a dynamic-format table and it is possible to
-            use a smaller static format table that can be used to find
-            the relevant rows when scanning the table.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-    </section>
-
-    <section id="indexes">
-
       <title>Column Indexes</title>
 
       <indexterm>

@@ -10079,7 +8895,7 @@
         MySQL can create composite indexes (that is, indexes on multiple
         columns). An index may consist of up to 16 columns. For certain
         data types, you can index a prefix of the column (see
-        <xref linkend="indexes"/>).
+        <xref linkend="column-indexes"/>).
       </para>
 
       <para>

@@ -11775,6 +10591,1196 @@
 
     </section>
 
+  </section>
+
+  <section id="locking-issues">
+
+    <title>Locking Issues</title>
+
+    <para>
+      MySQL manages contention for table contents using locking:
+    </para>
+
+    <itemizedlist>
+
+      <listitem>
+        <para>
+          Internal locking is performed within the MySQL server itself
+          to manage contention for table contents by multiple threads.
+          This type of locking is internal because it is performed
+          entirely by the server and involves no other programs. See
+          <xref linkend="internal-locking"/>.
+        </para>
+      </listitem>
+
+      <listitem>
+        <para>
+          External locking occurs when the server and other programs
+          lock table files to coordinate among themselves which program
+          can access the tables at which time. See
+          <xref linkend="external-locking"/>.
+        </para>
+      </listitem>
+
+    </itemizedlist>
+
+    <section id="internal-locking">
+
+      <title>Internal Locking Methods</title>
+
+      <indexterm>
+        <primary>internal locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>internal</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking methods</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>methods</primary>
+        <secondary>locking</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>row-level locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>table-level locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>row-level</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>table-level</secondary>
+      </indexterm>
+
+      <para>
+        This section discusses internal locking; that is, locking
+        performed within the MySQL server itself to manage contention
+        for table contents by multiple sessions. This type of locking is
+        internal because it is performed entirely by the server and
+        involves no other programs. External locking occurs when the
+        server and other programs lock table files to coordinate among
+        themselves which program can access the tables at which time.
+        See <xref linkend="external-locking"/>.
+      </para>
+
+      <para>
+        MySQL uses table-level locking for <literal>MyISAM</literal>,
+        <literal>MEMORY</literal>, and <literal>MERGE</literal> tables,
+        and row-level locking for <literal>InnoDB</literal> tables.
+      </para>
+
+      <para>
+        In many cases, you can make an educated guess about which
+        locking type is best for an application, but generally it is
+        difficult to say that a given lock type is better than another.
+        Everything depends on the application and different parts of an
+        application may require different lock types.
+      </para>
+
+      <para>
+        To decide whether you want to use a storage engine with
+        row-level locking, you should look at what your application does
+        and what mix of select and update statements it uses. For
+        example, most Web applications perform many selects, relatively
+        few deletes, updates based mainly on key values, and inserts
+        into a few specific tables. The base MySQL
+        <literal>MyISAM</literal> setup is very well tuned for this.
+      </para>
+
+      <formalpara role="mnmas">
+
+        <title>MySQL Enterprise</title>
+
+        <para>
+          The MySQL Enterprise Monitor provides expert advice on when to
+          use table-level locking and when to use row-level locking. To
+          subscribe, see &base-url-enterprise;advisors.html.
+        </para>
+
+      </formalpara>
+
+      <para>
+        Table locking in MySQL is deadlock-free for storage engines that
+        use table-level locking. Deadlock avoidance is managed by always
+        requesting all needed locks at once at the beginning of a query
+        and always locking the tables in the same order.
+      </para>
+
+      <para>
+        MySQL grants table write locks as follows:
+      </para>
+
+      <orderedlist>
+
+        <listitem>
+          <para>
+            If there are no locks on the table, put a write lock on it.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Otherwise, put the lock request in the write lock queue.
+          </para>
+        </listitem>
+
+      </orderedlist>
+
+      <para>
+        MySQL grants table read locks as follows:
+      </para>
+
+      <orderedlist>
+
+        <listitem>
+          <para>
+            If there are no write locks on the table, put a read lock on
+            it.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Otherwise, put the lock request in the read lock queue.
+          </para>
+        </listitem>
+
+      </orderedlist>
+
+      <para>
+        Table updates are given higher priority than table retrievals.
+        Therefore, when a lock is released, the lock is made available
+        to the requests in the write lock queue and then to the requests
+        in the read lock queue. This ensures that updates to a table are
+        not <quote>starved</quote> even if there is heavy
+        <literal role="stmt">SELECT</literal> activity for the table.
+        However, if you have many updates for a table,
+        <literal role="stmt">SELECT</literal> statements wait until
+        there are no more updates.
+      </para>
+
+      <para>
+        For information on altering the priority of reads and writes,
+        see <xref linkend="table-locking"/>.
+      </para>
+
+      <para>
+        You can analyze the table lock contention on your system by
+        checking the
+        <literal role="statvar">Table_locks_immediate</literal> and
+        <literal role="statvar">Table_locks_waited</literal> status
+        variables, which indicate the number of times that requests for
+        table locks could be granted immediately and the number that had
+        to wait, respectively:
+      </para>
+
+<programlisting>
+mysql&gt; <userinput>SHOW STATUS LIKE 'Table%';</userinput>
++-----------------------+---------+
+| Variable_name         | Value   |
++-----------------------+---------+
+| Table_locks_immediate | 1151552 |
+| Table_locks_waited    | 15324   |
++-----------------------+---------+
+</programlisting>
+
+      <indexterm>
+        <primary>concurrent inserts</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>inserts</primary>
+        <secondary>concurrent</secondary>
+      </indexterm>
+
+      <para>
+        The <literal>MyISAM</literal> storage engine supports concurrent
+        inserts to reduce contention between readers and writers for a
+        given table: If a <literal>MyISAM</literal> table has no free
+        blocks in the middle of the data file, rows are always inserted
+        at the end of the data file. In this case, you can freely mix
+        concurrent <literal role="stmt">INSERT</literal> and
+        <literal role="stmt">SELECT</literal> statements for a
+        <literal>MyISAM</literal> table without locks. That is, you can
+        insert rows into a <literal>MyISAM</literal> table at the same
+        time other clients are reading from it. Holes can result from
+        rows having been deleted from or updated in the middle of the
+        table. If there are holes, concurrent inserts are disabled but
+        are enabled again automatically when all holes have been filled
+        with new data.. This behavior is altered by the
+        <literal role="sysvar">concurrent_insert</literal> system
+        variable. See <xref linkend="concurrent-inserts"/>.
+      </para>
+
+      <para>
+        If you acquire a table lock explicitly with
+        <literal role="stmt">LOCK TABLES</literal>, you can request a
+        <literal>READ LOCAL</literal> lock rather than a
+        <literal>READ</literal> lock to enable other sessions to perform
+        concurrent inserts while you have the table locked.
+      </para>
+
+      <para>
+        To perform many <literal role="stmt">INSERT</literal> and
+        <literal role="stmt">SELECT</literal> operations on a table
+        <literal>real_table</literal> when concurrent inserts are not
+        possible, you can insert rows into a temporary table
+        <literal>temp_table</literal> and update the real table with the
+        rows from the temporary table periodically. This can be done
+        with the following code:
+      </para>
+
+<programlisting>
+mysql&gt; <userinput>LOCK TABLES real_table WRITE, temp_table WRITE;</userinput>
+mysql&gt; <userinput>INSERT INTO real_table SELECT * FROM temp_table;</userinput>
+mysql&gt; <userinput>DELETE FROM temp_table;</userinput>
+mysql&gt; <userinput>UNLOCK TABLES;</userinput>
+</programlisting>
+
+      <para>
+        <literal>InnoDB</literal> uses row locks. Deadlocks are possible
+        for <literal>InnoDB</literal> because it automatically acquires
+        locks during the processing of SQL statements, not at the start
+        of the transaction.
+      </para>
+
+      <para>
+        Advantages of row-level locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Fewer lock conflicts when different sessions access
+            different rows
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Fewer changes for rollbacks
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Possible to lock a single row for a long time
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Disadvantages of row-level locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Requires more memory than table-level locks
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Slower than table-level locks when used on a large part of
+            the table because you must acquire many more locks
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Slower than other locks if you often do <literal>GROUP
+            BY</literal> operations on a large part of the data or if
+            you must scan the entire table frequently
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Generally, table locks are superior to row-level locks in the
+        following cases:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Most statements for the table are reads
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Statements for the table are a mix of reads and writes,
+            where writes are updates or deletes for a single row that
+            can be fetched with one key read:
+          </para>
+
+<programlisting>
+UPDATE <replaceable>tbl_name</replaceable> SET <replaceable>column</replaceable>=<replaceable>value</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
+DELETE FROM <replaceable>tbl_name</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
+</programlisting>
+        </listitem>
+
+        <listitem>
+          <para>
+            <literal role="stmt">SELECT</literal> combined with
+            concurrent <literal role="stmt">INSERT</literal> statements,
+            and very few <literal role="stmt">UPDATE</literal> or
+            <literal role="stmt">DELETE</literal> statements
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Many scans or <literal>GROUP BY</literal> operations on the
+            entire table without any writers
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        With higher-level locks, you can more easily tune applications
+        by supporting locks of different types, because the lock
+        overhead is less than for row-level locks.
+      </para>
+
+      <para>
+        Options other than row-level locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Versioning (such as that used in MySQL for concurrent
+            inserts) where it is possible to have one writer at the same
+            time as many readers. This means that the database or table
+            supports different views for the data depending on when
+            access begins. Other common terms for this are <quote>time
+            travel,</quote> <quote>copy on write,</quote> or <quote>copy
+            on demand.</quote>
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Copy on demand is in many cases superior to row-level
+            locking. However, in the worst case, it can use much more
+            memory than using normal locks.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Instead of using row-level locks, you can employ
+            application-level locks, such as those provided by
+            <literal role="func">GET_LOCK()</literal> and
+            <literal role="func">RELEASE_LOCK()</literal> in MySQL.
+            These are advisory locks, so they work only with
+            applications that cooperate with each other. See
+            <xref linkend="miscellaneous-functions"/>.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+    </section>
+
+    <section id="table-locking">
+
+      <title>Table Locking Issues</title>
+
+      <indexterm>
+        <primary>problems</primary>
+        <secondary>table locking</secondary>
+      </indexterm>
+
+      <para>
+        To achieve a very high lock speed, MySQL uses table locking
+        (instead of page, row, or column locking) for all storage
+        engines except <literal>InnoDB</literal>.
+      </para>
+
+      <para>
+        For <literal>InnoDB</literal> tables, MySQL uses table locking
+        only if you explicitly lock the table with
+        <literal role="stmt">LOCK TABLES</literal>. For this storage
+        engine, avoid using <literal role="stmt">LOCK TABLES</literal>
+        at all, because <literal>InnoDB</literal> uses automatic
+        row-level locking to ensure transaction isolation.
+      </para>
+
+      <para>
+        For large tables, table locking is often better than row
+        locking, but there are some disadvantages:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Table locking enables many sessions to read from a table at
+            the same time, but if a session wants to write to a table,
+            it must first get exclusive access. During the update, all
+            other sessions that want to access this particular table
+            must wait until the update is done.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Table locking causes problems in cases such as when a
+            session is waiting because the disk is full and free space
+            needs to become available before the session can proceed. In
+            this case, all sessions that want to access the problem
+            table are also put in a waiting state until more disk space
+            is made available.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Table locking is also disadvantageous under the following
+        scenario:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            A session issues a <literal role="stmt">SELECT</literal>
+            that takes a long time to run.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Another session then issues an
+            <literal role="stmt">UPDATE</literal> on the same table.
+            This session waits until the
+            <literal role="stmt">SELECT</literal> is finished.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Another session issues another
+            <literal role="stmt">SELECT</literal> statement on the same
+            table. Because <literal role="stmt">UPDATE</literal> has
+            higher priority than <literal role="stmt">SELECT</literal>,
+            this <literal role="stmt">SELECT</literal> waits for the
+            <literal role="stmt">UPDATE</literal> to finish,
+            <emphasis>after</emphasis> waiting for the first
+            <literal role="stmt">SELECT</literal> to finish.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        The following items describe some ways to avoid or reduce
+        contention caused by table locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Try to get the <literal role="stmt">SELECT</literal>
+            statements to run faster so that they lock tables for a
+            shorter time. You might have to create some summary tables
+            to do this.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Start <command>mysqld</command> with
+            <option role="mysqld">--low-priority-updates</option>. For
+            storage engines that use only table-level locking (such as
+            <literal>MyISAM</literal>, <literal>MEMORY</literal>, and
+            <literal>MERGE</literal>), this gives all statements that
+            update (modify) a table lower priority than
+            <literal role="stmt">SELECT</literal> statements. In this
+            case, the second <literal role="stmt">SELECT</literal>
+            statement in the preceding scenario would execute before the
+            <literal role="stmt">UPDATE</literal> statement, and would
+            not need to wait for the first
+            <literal role="stmt">SELECT</literal> to finish.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            To specify that all updates issued in a specific connection
+            should be done with low priority, set the
+            <literal role="sysvar">low_priority_updates</literal> server
+            system variable equal to 1.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            To give a specific <literal role="stmt">INSERT</literal>,
+            <literal role="stmt">UPDATE</literal>, or
+            <literal role="stmt">DELETE</literal> statement lower
+            priority, use the <literal>LOW_PRIORITY</literal> attribute.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            To give a specific <literal role="stmt">SELECT</literal>
+            statement higher priority, use the
+            <literal>HIGH_PRIORITY</literal> attribute. See
+            <xref linkend="select"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Start <command>mysqld</command> with a low value for the
+            <literal role="sysvar">max_write_lock_count</literal> system
+            variable to force MySQL to temporarily elevate the priority
+            of all <literal role="stmt">SELECT</literal> statements that
+            are waiting for a table after a specific number of inserts
+            to the table occur. This permits <literal>READ</literal>
+            locks after a certain number of <literal>WRITE</literal>
+            locks.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you have problems with
+            <literal role="stmt">INSERT</literal> combined with
+            <literal role="stmt">SELECT</literal>, consider switching to
+            <literal>MyISAM</literal> tables, which support concurrent
+            <literal role="stmt">SELECT</literal> and
+            <literal role="stmt">INSERT</literal> statements. (See
+            <xref linkend="concurrent-inserts"/>.)
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you mix inserts and deletes on the same table,
+            <literal role="stmt">INSERT DELAYED</literal> may be of
+            great help. See <xref linkend="insert-delayed"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you have problems with mixed
+            <literal role="stmt">SELECT</literal> and
+            <literal role="stmt">DELETE</literal> statements, the
+            <literal>LIMIT</literal> option to
+            <literal role="stmt">DELETE</literal> may help. See
+            <xref linkend="delete"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Using <literal>SQL_BUFFER_RESULT</literal> with
+            <literal role="stmt">SELECT</literal> statements can help to
+            make the duration of table locks shorter. See
+            <xref linkend="select"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            You could change the locking code in
+            <filename>mysys/thr_lock.c</filename> to use a single queue.
+            In this case, write locks and read locks would have the same
+            priority, which might help some applications.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Here are some tips concerning table locks in MySQL:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Concurrent users are not a problem if you do not mix updates
+            with selects that need to examine many rows in the same
+            table.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            You can use <literal role="stmt">LOCK TABLES</literal> to
+            increase speed, because many updates within a single lock is
+            much faster than updating without locks. Splitting table
+            contents into separate tables may also help.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you encounter speed problems with table locks in MySQL,
+            you may be able to improve performance by converting some of
+            your tables to <literal>InnoDB</literal>. See
+            <xref linkend="innodb"/>.
+          </para>
+
+          <formalpara role="mnmas">
+
+            <title>MySQL Enterprise</title>
+
+            <para>
+              Lock contention can seriously degrade performance. The
+              MySQL Enterprise Monitor provides expert advice on
+              avoiding this problem. To subscribe, see
+              &base-url-enterprise;advisors.html.
+            </para>
+
+          </formalpara>
+        </listitem>
+
+      </itemizedlist>
+
+    </section>
+
+    <section id="concurrent-inserts">
+
+      <title>Concurrent Inserts</title>
+
+      <indexterm>
+        <primary>concurrent inserts</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>inserts</primary>
+        <secondary>concurrent</secondary>
+      </indexterm>
+
+      <para>
+        The <literal>MyISAM</literal> storage engine supports concurrent
+        inserts to reduce contention between readers and writers for a
+        given table: If a <literal>MyISAM</literal> table has no holes
+        in the data file (deleted rows in the middle), an
+        <literal role="stmt">INSERT</literal> statement can be executed
+        to add rows to the end of the table at the same time that
+        <literal role="stmt">SELECT</literal> statements are reading
+        rows from the table. If there are multiple
+        <literal role="stmt">INSERT</literal> statements, they are
+        queued and performed in sequence, concurrently with the
+        <literal role="stmt">SELECT</literal> statements. The results of
+        a concurrent <literal role="stmt">INSERT</literal> may not be
+        visible immediately.
+      </para>
+
+      <para>
+        The <literal role="sysvar">concurrent_insert</literal> system
+        variable can be set to modify the concurrent-insert processing.
+        By default, the variable is set to <literal>AUTO</literal> (or
+        1) and concurrent inserts are handled as just described. If
+        <literal role="sysvar">concurrent_insert</literal> is set to
+        <literal>NEVER</literal> (or 0), concurrent inserts are
+        disabled. If the variable is set to <literal>ALWAYS</literal>
+        (or 2), concurrent inserts at the end of the table are allowed
+        even for tables that have deleted rows. See also the description
+        of the
+        <link linkend="sysvar_concurrent_insert"><literal role="sysvar">concurrent_insert</literal></link>
+        system variable.
+      </para>
+
+      <para>
+        Under circumstances where concurrent inserts can be used, there
+        is seldom any need to use the <literal>DELAYED</literal>
+        modifier for <literal role="stmt">INSERT</literal> statements.
+        See <xref linkend="insert-delayed"/>.
+      </para>
+
+      <para>
+        If you are using the binary log, concurrent inserts are
+        converted to normal inserts for <literal>CREATE ...
+        SELECT</literal> or
+        <literal role="stmt" condition="insert-select">INSERT ...
+        SELECT</literal> statements. This is done to ensure that you can
+        re-create an exact copy of your tables by applying the log
+        during a backup operation. See <xref linkend="binary-log"/>. In
+        addition, for those statements a read lock is placed on the
+        selected-from table such that inserts into that table are
+        blocked. The effect is that concurrent inserts for that table
+        must wait as well.
+      </para>
+
+      <para>
+        With <literal role="stmt" condition="load-data">LOAD DATA
+        INFILE</literal>, if you specify <literal>CONCURRENT</literal>
+        with a <literal>MyISAM</literal> table that satisfies the
+        condition for concurrent inserts (that is, it contains no free
+        blocks in the middle), other sessions can retrieve data from the
+        table while <literal role="stmt">LOAD DATA</literal> is
+        executing. Use of the <literal>CONCURRENT</literal> option
+        affects the performance of <literal role="stmt">LOAD
+        DATA</literal> a bit, even if no other session is using the
+        table at the same time.
+      </para>
+
+      <para>
+        If you specify <literal>HIGH_PRIORITY</literal>, it overrides
+        the effect of the
+        <option role="mysqld">--low-priority-updates</option> option if
+        the server was started with that option. It also causes
+        concurrent inserts not to be used.
+      </para>
+
+      <para>
+        For <literal role="stmt" condition="lock-tables">LOCK
+        TABLE</literal>, the difference between <literal>READ
+        LOCAL</literal> and <literal>READ</literal> is that
+        <literal>READ LOCAL</literal> permits nonconflicting
+        <literal role="stmt">INSERT</literal> statements (concurrent
+        inserts) to execute while the lock is held. However, this cannot
+        be used if you are going to manipulate the database using
+        processes external to the server while you hold the lock.
+      </para>
+
+    </section>
+
+    <section id="metadata-locking">
+
+      <title>Metadata Locking Within Transactions</title>
+
+      <indexterm>
+        <primary>metadata locking</primary>
+        <secondary>transactions</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>transactions</primary>
+        <secondary>metadata locking</secondary>
+      </indexterm>
+
+      <para>
+        To ensure transaction serializability, the server must not allow
+        one session to perform a data definition language (DDL)
+        statement on a table that is used in an uncompleted transaction
+        in another session.
+      </para>
+
+      <para>
+        As of MySQL 5.5.3, the server achieves this by acquiring
+        metadata locks on tables used within a transaction and deferring
+        release of those locks until the transaction ends. A metadata
+        lock on a table prevents changes to the table's structure. This
+        locking approach has the implication that a table that is being
+        used by a transaction within one session cannot be used in DDL
+        statements by other sessions until the transaction ends. For
+        example, if a table <literal>t1</literal> is in use by a
+        transaction, another session that attempts to execute
+        <literal role="stmt" condition="drop-table">DROP TABLE
+        t1</literal> will block until the transaction ends.
+      </para>
+
+      <para>
+        If the server acquires metadata locks for a statement that is
+        syntactically valid but fails during execution, it does not
+        release the locks early. Lock release is still deferred to the
+        end of the transaction because the failed statement is written
+        to the binary log and the locks protect log consistency.
+      </para>
+
+      <para>
+        Metadata locks acquired during a
+        <literal role="stmt">PREPARE</literal> statement are released
+        once the statement has been prepared, even if preparation occurs
+        within a multiple-statement transaction.
+      </para>
+
+      <para>
+        Before MySQL 5.5.3, when a transaction acquired a metadata lock
+        for a table used within a statement, it released the lock at the
+        end of the statement. This approach had the disadvantage that if
+        a DDL statement occurred for a table that was being used by
+        another session in an active transaction, statements could be
+        written to the binary log in the wrong order.
+      </para>
+
+    </section>
+
+    <section id="external-locking">
+
+      <title>External Locking</title>
+
+      <indexterm>
+        <primary>external locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>external</secondary>
+      </indexterm>
+
+      <para>
+        External locking is the use of file system locking to manage
+        contention for database tables by multiple processes. External
+        locking is used in situations where a single process such as the
+        MySQL server cannot be assumed to be the only process that
+        requires access to tables. Here are some examples:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            If you run multiple servers that use the same database
+            directory (not recommended), each server must have external
+            locking enabled.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you use <command>myisamchk</command> to perform table
+            maintenance operations on <literal>MyISAM</literal> tables,
+            you must either ensure that the server is not running, or
+            that the server has external locking enabled so that it
+            locks table files as necessary to coordinate with
+            <command>myisamchk</command> for access to the tables. The
+            same is true for use of <command>myisampack</command> to
+            pack <literal>MyISAM</literal> tables.
+          </para>
+
+          <para>
+            If the server is run with external locking enabled, you can
+            use <command>myisamchk</command> at any time for read
+            operations such a checking tables. In this case, if the
+            server tries to update a table that
+            <command>myisamchk</command> is using, the server will wait
+            for <command>myisamchk</command> to finish before it
+            continues.
+          </para>
+
+          <para>
+            If you use <command>myisamchk</command> for write operations
+            such as repairing or optimizing tables, or if you use
+            <command>myisampack</command> to pack tables, you
+            <emphasis>must</emphasis> always ensure that the
+            <command>mysqld</command> server is not using the table. If
+            you don't stop <command>mysqld</command>, you should at
+            least do a <command>mysqladmin flush-tables</command> before
+            you run <command>myisamchk</command>. Your tables
+            <emphasis>may become corrupted</emphasis> if the server and
+            <command>myisamchk</command> access the tables
+            simultaneously.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        With external locking in effect, each process that requires
+        access to a table acquires a file system lock for the table
+        files before proceeding to access the table. If all necessary
+        locks cannot be acquired, the process is blocked from accessing
+        the table until the locks can be obtained (after the process
+        that currently holds the locks releases them).
+      </para>
+
+      <para>
+        External locking affects server performance because the server
+        must sometimes wait for other processes before it can access
+        tables.
+      </para>
+
+      <para>
+        External locking is unnecessary if you run a single server to
+        access a given data directory (which is the usual case) and if
+        no other programs such as <command>myisamchk</command> need to
+        modify tables while the server is running. If you only
+        <emphasis>read</emphasis> tables with other programs, external
+        locking is not required, although <command>myisamchk</command>
+        might report warnings if the server changes tables while
+        <command>myisamchk</command> is reading them.
+      </para>
+
+      <para>
+        With external locking disabled, to use
+        <command>myisamchk</command>, you must either stop the server
+        while <command>myisamchk</command> executes or else lock and
+        flush the tables before running <command>myisamchk</command>.
+        (See <xref linkend="system-optimization"/>.) To avoid this
+        requirement, use the <literal role="stmt">CHECK TABLE</literal>
+        and <literal role="stmt">REPAIR TABLE</literal> statements to
+        check and repair <literal>MyISAM</literal> tables.
+      </para>
+
+      <para>
+        For <command>mysqld</command>, external locking is controlled by
+        the value of the
+        <literal role="sysvar">skip_external_locking</literal> system
+        variable. When this variable is enabled, external locking is
+        disabled, and vice versa. From MySQL 4.0 on, external locking is
+        disabled by default. Before MySQL 4.0, external locking is
+        enabled by default on Linux or when MySQL is configured to use
+        MIT-pthreads.
+      </para>
+
+      <para>
+        Use of external locking can be controlled at server startup by
+        using the <option role="mysqld">--external-locking</option> or
+        <option role="mysqld">--skip-external-locking</option> option.
+      </para>
+
+      <para>
+        If you do use external locking option to enable updates to
+        <literal>MyISAM</literal> tables from many MySQL processes, you
+        must ensure that the following conditions are satisfied:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            You should not use the query cache for queries that use
+            tables that are updated by another process.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            You should not start the server with the
+            <option role="mysqld">--delay-key-write=ALL</option> option
+            or use the <literal>DELAY_KEY_WRITE=1</literal> table option
+            for any shared tables. Otherwise, index corruption can
+            occur.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        The easiest way to satisfy these conditions is to always use
+        <option role="mysqld">--external-locking</option> together with
+        <option role="mysqld">--delay-key-write=OFF</option> and
+        <option role="sysvar">--query-cache-size=0</option>. (This is
+        not done by default because in many setups it is useful to have
+        a mixture of the preceding options.)
+      </para>
+
+    </section>
+
+  </section>
+
+  <section id="optimizing-database-structure">
+
+    <title>Optimizing Database Structure</title>
+
+    <section id="data-size">
+
+      <title>Make Your Data as Small as Possible</title>
+
+      <indexterm>
+        <primary>data</primary>
+        <secondary>size</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>reducing</primary>
+        <secondary>data size</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>storage space</primary>
+        <secondary>minimizing</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>tables</primary>
+        <secondary>improving performance</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>performance</primary>
+        <secondary>improving</secondary>
+      </indexterm>
+
+      <para>
+        One of the most basic optimizations is to design your tables to
+        take as little space on the disk as possible. This can result in
+        huge improvements because disk reads are faster, and smaller
+        tables normally require less main memory while their contents
+        are being actively processed during query execution. Indexing
+        also is a lesser resource burden if done on smaller columns.
+      </para>
+
+      <para>
+        MySQL supports many different storage engines (table types) and
+        row formats. For each table, you can decide which storage and
+        indexing method to use. Choosing the proper table format for
+        your application may give you a big performance gain. See
+        <xref linkend="storage-engines"/>.
+      </para>
+
+      <para>
+        You can get better performance for a table and minimize storage
+        space by using the techniques listed here:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Use the most efficient (smallest) data types possible. MySQL
+            has many specialized types that save disk space and memory.
+            For example, use the smaller integer types if possible to
+            get smaller tables. <literal role="type">MEDIUMINT</literal>
+            is often a better choice than
+            <literal role="type">INT</literal> because a
+            <literal role="type">MEDIUMINT</literal> column uses 25%
+            less space.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Declare columns to be <literal>NOT NULL</literal> if
+            possible. It makes everything faster and you save one bit
+            per column. If you really need <literal>NULL</literal> in
+            your application, you should definitely use it. Just avoid
+            having it on all columns by default.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            For <literal>MyISAM</literal> tables, if you do not have any
+            variable-length columns
+            (<literal role="type">VARCHAR</literal>,
+            <literal role="type">TEXT</literal>, or
+            <literal role="type">BLOB</literal> columns), a fixed-size
+            row format is used. This is faster but unfortunately may
+            waste some space. See
+            <xref linkend="myisam-table-formats"/>. You can hint that
+            you want to have fixed length rows even if you have
+            <literal role="type">VARCHAR</literal> columns with the
+            <literal role="stmt">CREATE TABLE</literal> option
+            <literal>ROW_FORMAT=FIXED</literal>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            <literal>InnoDB</literal> tables use a compact storage
+            format. In versions of MySQL earlier than 5.0.3,
+            <literal>InnoDB</literal> rows contain some redundant
+            information, such as the number of columns and the length of
+            each column, even for fixed-size columns. By default, tables
+            are created in the compact format
+            (<literal>ROW_FORMAT=COMPACT</literal>). If you wish to
+            downgrade to older versions of MySQL, you can request the
+            old format with <literal>ROW_FORMAT=REDUNDANT</literal>.
+          </para>
+
+          <para>
+            The presence of the compact row format decreases row storage
+            space by about 20% at the cost of increasing CPU use for
+            some operations. If your workload is a typical one that is
+            limited by cache hit rates and disk speed it is likely to be
+            faster. If it is a rare case that is limited by CPU speed,
+            it might be slower.
+          </para>
+
+          <para>
+            The compact <literal>InnoDB</literal> format also changes
+            how <literal role="type">CHAR</literal> columns containing
+            UTF-8 data are stored. With
+            <literal>ROW_FORMAT=REDUNDANT</literal>, a UTF-8
+            <literal>CHAR(<replaceable>N</replaceable>)</literal>
+            occupies 3 &times; <replaceable>N</replaceable> bytes, given
+            that the maximum length of a UTF-8 encoded character is
+            three bytes. Many languages can be written primarily using
+            single-byte UTF-8 characters, so a fixed storage length
+            often wastes space. With
+            <literal>ROW_FORMAT=COMPACT</literal> format,
+            <literal>InnoDB</literal> allocates a variable amount of
+            storage in the range from <replaceable>N</replaceable> to 3
+            &times; <replaceable>N</replaceable> bytes for these columns
+            by stripping trailing spaces if necessary. The minimum
+            storage length is kept as <replaceable>N</replaceable> bytes
+            to facilitate in-place updates in typical cases.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            The primary index of a table should be as short as possible.
+            This makes identification of each row easy and efficient.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Create only the indexes that you really need. Indexes are
+            good for retrieval but bad when you need to store data
+            quickly. If you access a table mostly by searching on a
+            combination of columns, create an index on them. The first
+            part of the index should be the column most used. If you
+            <emphasis>always</emphasis> use many columns when selecting
+            from the table, the first column in the index should be the
+            one with the most duplicates to obtain better compression of
+            the index.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If it is very likely that a string column has a unique
+            prefix on the first number of characters, it is better to
+            index only this prefix, using MySQL's support for creating
+            an index on the leftmost part of the column (see
+            <xref linkend="create-index"/>). Shorter indexes are faster,
+            not only because they require less disk space, but because
+            they also give you more hits in the index cache, and thus
+            fewer disk seeks. See <xref linkend="server-parameters"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            In some circumstances, it can be beneficial to split into
+            two a table that is scanned very often. This is especially
+            true if it is a dynamic-format table and it is possible to
+            use a smaller static format table that can be used to find
+            the relevant rows when scanning the table.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+    </section>
+
     <section id="table-cache">
 
       <title>How MySQL Opens and Closes Tables</title>


Modified: trunk/refman-5.5/renamed-nodes.txt
===================================================================
--- trunk/refman-5.5/renamed-nodes.txt	2010-07-14 15:11:37 UTC (rev 21727)
+++ trunk/refman-5.5/renamed-nodes.txt	2010-07-14 15:35:58 UTC (rev 21728)
Changed blocks: 1, Lines Added: 1, Lines Deleted: 0; 624 bytes

@@ -26,6 +26,7 @@
 change-column-order alter-table 2011-04-09
 charset-collate-tricky charset-collation-expressions 2011-06-14
 index-condition-pushdown-optimization condition-pushdown-optimization 2011-06-23
+indexes column-indexes 2011-07-14
 load-data-from-master introduction 2011-03-06
 load-table-from-master introduction 2011-03-06
 mysql-copyright index 2011-04-09


Modified: trunk/refman-5.5/sql-syntax-data-definition.xml
===================================================================
--- trunk/refman-5.5/sql-syntax-data-definition.xml	2010-07-14 15:11:37 UTC (rev 21727)
+++ trunk/refman-5.5/sql-syntax-data-definition.xml	2010-07-14 15:35:58 UTC (rev 21728)
Changed blocks: 1, Lines Added: 1, Lines Deleted: 1; 663 bytes

@@ -4790,7 +4790,7 @@
           <literal role="type">VARBINARY</literal>, and
           <literal role="type">BLOB</literal> columns. Indexing only a
           prefix of column values like this can make the index file much
-          smaller. See <xref linkend="indexes"/>.
+          smaller. See <xref linkend="column-indexes"/>.
         </para>
 
         <indexterm>


Modified: trunk/refman-6.0/data-types.xml
===================================================================
--- trunk/refman-6.0/data-types.xml	2010-07-14 15:11:37 UTC (rev 21727)
+++ trunk/refman-6.0/data-types.xml	2010-07-14 15:35:58 UTC (rev 21728)
Changed blocks: 1, Lines Added: 1, Lines Deleted: 1; 594 bytes

@@ -4644,7 +4644,7 @@
             specify an index prefix length. For
             <literal role="type">CHAR</literal> and
             <literal role="type">VARCHAR</literal>, a prefix length is
-            optional. See <xref linkend="indexes"/>.
+            optional. See <xref linkend="column-indexes"/>.
           </para>
         </listitem>
 


Modified: trunk/refman-6.0/optimization.xml
===================================================================
--- trunk/refman-6.0/optimization.xml	2010-07-14 15:11:37 UTC (rev 21727)
+++ trunk/refman-6.0/optimization.xml	2010-07-14 15:35:58 UTC (rev 21728)
Changed blocks: 3, Lines Added: 1194, Lines Deleted: 1188; 88254 bytes

@@ -9929,1196 +9929,12 @@
 
   </section>
 
-  <section id="locking-issues">
+  <section id="optimization-indexes">
 
-    <title>Locking Issues</title>
+    <title>Optimization and Indexes</title>
 
-    <para>
-      MySQL manages contention for table contents using locking:
-    </para>
+    <section id="column-indexes">
 
-    <itemizedlist>
-
-      <listitem>
-        <para>
-          Internal locking is performed within the MySQL server itself
-          to manage contention for table contents by multiple threads.
-          This type of locking is internal because it is performed
-          entirely by the server and involves no other programs. See
-          <xref linkend="internal-locking"/>.
-        </para>
-      </listitem>
-
-      <listitem>
-        <para>
-          External locking occurs when the server and other programs
-          lock table files to coordinate among themselves which program
-          can access the tables at which time. See
-          <xref linkend="external-locking"/>.
-        </para>
-      </listitem>
-
-    </itemizedlist>
-
-    <section id="internal-locking">
-
-      <title>Internal Locking Methods</title>
-
-      <indexterm>
-        <primary>internal locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>internal</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking methods</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>methods</primary>
-        <secondary>locking</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>row-level locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>table-level locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>row-level</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>table-level</secondary>
-      </indexterm>
-
-      <para>
-        This section discusses internal locking; that is, locking
-        performed within the MySQL server itself to manage contention
-        for table contents by multiple sessions. This type of locking is
-        internal because it is performed entirely by the server and
-        involves no other programs. External locking occurs when the
-        server and other programs lock table files to coordinate among
-        themselves which program can access the tables at which time.
-        See <xref linkend="external-locking"/>.
-      </para>
-
-      <para>
-        MySQL uses table-level locking for <literal>MyISAM</literal>,
-        <literal>MEMORY</literal>, and <literal>MERGE</literal> tables,
-        and row-level locking for <literal>InnoDB</literal> tables.
-      </para>
-
-      <para>
-        In many cases, you can make an educated guess about which
-        locking type is best for an application, but generally it is
-        difficult to say that a given lock type is better than another.
-        Everything depends on the application and different parts of an
-        application may require different lock types.
-      </para>
-
-      <para>
-        To decide whether you want to use a storage engine with
-        row-level locking, you should look at what your application does
-        and what mix of select and update statements it uses. For
-        example, most Web applications perform many selects, relatively
-        few deletes, updates based mainly on key values, and inserts
-        into a few specific tables. The base MySQL
-        <literal>MyISAM</literal> setup is very well tuned for this.
-      </para>
-
-      <formalpara role="mnmas">
-
-        <title>MySQL Enterprise</title>
-
-        <para>
-          The MySQL Enterprise Monitor provides expert advice on when to
-          use table-level locking and when to use row-level locking. To
-          subscribe, see &base-url-enterprise;advisors.html.
-        </para>
-
-      </formalpara>
-
-      <para>
-        Table locking in MySQL is deadlock-free for storage engines that
-        use table-level locking. Deadlock avoidance is managed by always
-        requesting all needed locks at once at the beginning of a query
-        and always locking the tables in the same order.
-      </para>
-
-      <para>
-        MySQL grants table write locks as follows:
-      </para>
-
-      <orderedlist>
-
-        <listitem>
-          <para>
-            If there are no locks on the table, put a write lock on it.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Otherwise, put the lock request in the write lock queue.
-          </para>
-        </listitem>
-
-      </orderedlist>
-
-      <para>
-        MySQL grants table read locks as follows:
-      </para>
-
-      <orderedlist>
-
-        <listitem>
-          <para>
-            If there are no write locks on the table, put a read lock on
-            it.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Otherwise, put the lock request in the read lock queue.
-          </para>
-        </listitem>
-
-      </orderedlist>
-
-      <para>
-        Table updates are given higher priority than table retrievals.
-        Therefore, when a lock is released, the lock is made available
-        to the requests in the write lock queue and then to the requests
-        in the read lock queue. This ensures that updates to a table are
-        not <quote>starved</quote> even if there is heavy
-        <literal role="stmt">SELECT</literal> activity for the table.
-        However, if you have many updates for a table,
-        <literal role="stmt">SELECT</literal> statements wait until
-        there are no more updates.
-      </para>
-
-      <para>
-        For information on altering the priority of reads and writes,
-        see <xref linkend="table-locking"/>.
-      </para>
-
-      <para>
-        You can analyze the table lock contention on your system by
-        checking the
-        <literal role="statvar">Table_locks_immediate</literal> and
-        <literal role="statvar">Table_locks_waited</literal> status
-        variables, which indicate the number of times that requests for
-        table locks could be granted immediately and the number that had
-        to wait, respectively:
-      </para>
-
-<programlisting>
-mysql&gt; <userinput>SHOW STATUS LIKE 'Table%';</userinput>
-+-----------------------+---------+
-| Variable_name         | Value   |
-+-----------------------+---------+
-| Table_locks_immediate | 1151552 |
-| Table_locks_waited    | 15324   |
-+-----------------------+---------+
-</programlisting>
-
-      <indexterm>
-        <primary>concurrent inserts</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>inserts</primary>
-        <secondary>concurrent</secondary>
-      </indexterm>
-
-      <para>
-        The <literal>MyISAM</literal> storage engine supports concurrent
-        inserts to reduce contention between readers and writers for a
-        given table: If a <literal>MyISAM</literal> table has no free
-        blocks in the middle of the data file, rows are always inserted
-        at the end of the data file. In this case, you can freely mix
-        concurrent <literal role="stmt">INSERT</literal> and
-        <literal role="stmt">SELECT</literal> statements for a
-        <literal>MyISAM</literal> table without locks. That is, you can
-        insert rows into a <literal>MyISAM</literal> table at the same
-        time other clients are reading from it. Holes can result from
-        rows having been deleted from or updated in the middle of the
-        table. If there are holes, concurrent inserts are disabled but
-        are enabled again automatically when all holes have been filled
-        with new data.. This behavior is altered by the
-        <literal role="sysvar">concurrent_insert</literal> system
-        variable. See <xref linkend="concurrent-inserts"/>.
-      </para>
-
-      <para>
-        If you acquire a table lock explicitly with
-        <literal role="stmt">LOCK TABLES</literal>, you can request a
-        <literal>READ LOCAL</literal> lock rather than a
-        <literal>READ</literal> lock to enable other sessions to perform
-        concurrent inserts while you have the table locked.
-      </para>
-
-      <para>
-        To perform many <literal role="stmt">INSERT</literal> and
-        <literal role="stmt">SELECT</literal> operations on a table
-        <literal>real_table</literal> when concurrent inserts are not
-        possible, you can insert rows into a temporary table
-        <literal>temp_table</literal> and update the real table with the
-        rows from the temporary table periodically. This can be done
-        with the following code:
-      </para>
-
-<programlisting>
-mysql&gt; <userinput>LOCK TABLES real_table WRITE, temp_table WRITE;</userinput>
-mysql&gt; <userinput>INSERT INTO real_table SELECT * FROM temp_table;</userinput>
-mysql&gt; <userinput>DELETE FROM temp_table;</userinput>
-mysql&gt; <userinput>UNLOCK TABLES;</userinput>
-</programlisting>
-
-      <para>
-        <literal>InnoDB</literal> uses row locks. Deadlocks are possible
-        for <literal>InnoDB</literal> because it automatically acquires
-        locks during the processing of SQL statements, not at the start
-        of the transaction.
-      </para>
-
-      <para>
-        Advantages of row-level locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Fewer lock conflicts when different sessions access
-            different rows
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Fewer changes for rollbacks
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Possible to lock a single row for a long time
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Disadvantages of row-level locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Requires more memory than table-level locks
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Slower than table-level locks when used on a large part of
-            the table because you must acquire many more locks
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Slower than other locks if you often do <literal>GROUP
-            BY</literal> operations on a large part of the data or if
-            you must scan the entire table frequently
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Generally, table locks are superior to row-level locks in the
-        following cases:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Most statements for the table are reads
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Statements for the table are a mix of reads and writes,
-            where writes are updates or deletes for a single row that
-            can be fetched with one key read:
-          </para>
-
-<programlisting>
-UPDATE <replaceable>tbl_name</replaceable> SET <replaceable>column</replaceable>=<replaceable>value</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
-DELETE FROM <replaceable>tbl_name</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
-</programlisting>
-        </listitem>
-
-        <listitem>
-          <para>
-            <literal role="stmt">SELECT</literal> combined with
-            concurrent <literal role="stmt">INSERT</literal> statements,
-            and very few <literal role="stmt">UPDATE</literal> or
-            <literal role="stmt">DELETE</literal> statements
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Many scans or <literal>GROUP BY</literal> operations on the
-            entire table without any writers
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        With higher-level locks, you can more easily tune applications
-        by supporting locks of different types, because the lock
-        overhead is less than for row-level locks.
-      </para>
-
-      <para>
-        Options other than row-level locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Versioning (such as that used in MySQL for concurrent
-            inserts) where it is possible to have one writer at the same
-            time as many readers. This means that the database or table
-            supports different views for the data depending on when
-            access begins. Other common terms for this are <quote>time
-            travel,</quote> <quote>copy on write,</quote> or <quote>copy
-            on demand.</quote>
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Copy on demand is in many cases superior to row-level
-            locking. However, in the worst case, it can use much more
-            memory than using normal locks.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Instead of using row-level locks, you can employ
-            application-level locks, such as those provided by
-            <literal role="func">GET_LOCK()</literal> and
-            <literal role="func">RELEASE_LOCK()</literal> in MySQL.
-            These are advisory locks, so they work only with
-            applications that cooperate with each other. See
-            <xref linkend="miscellaneous-functions"/>.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-    </section>
-
-    <section id="table-locking">
-
-      <title>Table Locking Issues</title>
-
-      <indexterm>
-        <primary>problems</primary>
-        <secondary>table locking</secondary>
-      </indexterm>
-
-      <para>
-        To achieve a very high lock speed, MySQL uses table locking
-        (instead of page, row, or column locking) for all storage
-        engines except <literal>InnoDB</literal>.
-      </para>
-
-      <para>
-        For <literal>InnoDB</literal> tables, MySQL uses table locking
-        only if you explicitly lock the table with
-        <literal role="stmt">LOCK TABLES</literal>. For this storage
-        engine, avoid using <literal role="stmt">LOCK TABLES</literal>
-        at all, because <literal>InnoDB</literal> uses automatic
-        row-level locking to ensure transaction isolation.
-      </para>
-
-      <para>
-        For large tables, table locking is often better than row
-        locking, but there are some disadvantages:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Table locking enables many sessions to read from a table at
-            the same time, but if a session wants to write to a table,
-            it must first get exclusive access. During the update, all
-            other sessions that want to access this particular table
-            must wait until the update is done.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Table locking causes problems in cases such as when a
-            session is waiting because the disk is full and free space
-            needs to become available before the session can proceed. In
-            this case, all sessions that want to access the problem
-            table are also put in a waiting state until more disk space
-            is made available.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Table locking is also disadvantageous under the following
-        scenario:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            A session issues a <literal role="stmt">SELECT</literal>
-            that takes a long time to run.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Another session then issues an
-            <literal role="stmt">UPDATE</literal> on the same table.
-            This session waits until the
-            <literal role="stmt">SELECT</literal> is finished.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Another session issues another
-            <literal role="stmt">SELECT</literal> statement on the same
-            table. Because <literal role="stmt">UPDATE</literal> has
-            higher priority than <literal role="stmt">SELECT</literal>,
-            this <literal role="stmt">SELECT</literal> waits for the
-            <literal role="stmt">UPDATE</literal> to finish,
-            <emphasis>after</emphasis> waiting for the first
-            <literal role="stmt">SELECT</literal> to finish.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        The following items describe some ways to avoid or reduce
-        contention caused by table locking:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Try to get the <literal role="stmt">SELECT</literal>
-            statements to run faster so that they lock tables for a
-            shorter time. You might have to create some summary tables
-            to do this.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Start <command>mysqld</command> with
-            <option role="mysqld">--low-priority-updates</option>. For
-            storage engines that use only table-level locking (such as
-            <literal>MyISAM</literal>, <literal>MEMORY</literal>, and
-            <literal>MERGE</literal>), this gives all statements that
-            update (modify) a table lower priority than
-            <literal role="stmt">SELECT</literal> statements. In this
-            case, the second <literal role="stmt">SELECT</literal>
-            statement in the preceding scenario would execute before the
-            <literal role="stmt">UPDATE</literal> statement, and would
-            not need to wait for the first
-            <literal role="stmt">SELECT</literal> to finish.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            To specify that all updates issued in a specific connection
-            should be done with low priority, set the
-            <literal role="sysvar">low_priority_updates</literal> server
-            system variable equal to 1.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            To give a specific <literal role="stmt">INSERT</literal>,
-            <literal role="stmt">UPDATE</literal>, or
-            <literal role="stmt">DELETE</literal> statement lower
-            priority, use the <literal>LOW_PRIORITY</literal> attribute.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            To give a specific <literal role="stmt">SELECT</literal>
-            statement higher priority, use the
-            <literal>HIGH_PRIORITY</literal> attribute. See
-            <xref linkend="select"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Start <command>mysqld</command> with a low value for the
-            <literal role="sysvar">max_write_lock_count</literal> system
-            variable to force MySQL to temporarily elevate the priority
-            of all <literal role="stmt">SELECT</literal> statements that
-            are waiting for a table after a specific number of inserts
-            to the table occur. This permits <literal>READ</literal>
-            locks after a certain number of <literal>WRITE</literal>
-            locks.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you have problems with
-            <literal role="stmt">INSERT</literal> combined with
-            <literal role="stmt">SELECT</literal>, consider switching to
-            <literal>MyISAM</literal> tables, which support concurrent
-            <literal role="stmt">SELECT</literal> and
-            <literal role="stmt">INSERT</literal> statements. (See
-            <xref linkend="concurrent-inserts"/>.)
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you mix inserts and deletes on the same table,
-            <literal role="stmt">INSERT DELAYED</literal> may be of
-            great help. See <xref linkend="insert-delayed"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you have problems with mixed
-            <literal role="stmt">SELECT</literal> and
-            <literal role="stmt">DELETE</literal> statements, the
-            <literal>LIMIT</literal> option to
-            <literal role="stmt">DELETE</literal> may help. See
-            <xref linkend="delete"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Using <literal>SQL_BUFFER_RESULT</literal> with
-            <literal role="stmt">SELECT</literal> statements can help to
-            make the duration of table locks shorter. See
-            <xref linkend="select"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            You could change the locking code in
-            <filename>mysys/thr_lock.c</filename> to use a single queue.
-            In this case, write locks and read locks would have the same
-            priority, which might help some applications.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        Here are some tips concerning table locks in MySQL:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Concurrent users are not a problem if you do not mix updates
-            with selects that need to examine many rows in the same
-            table.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            You can use <literal role="stmt">LOCK TABLES</literal> to
-            increase speed, because many updates within a single lock is
-            much faster than updating without locks. Splitting table
-            contents into separate tables may also help.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you encounter speed problems with table locks in MySQL,
-            you may be able to improve performance by converting some of
-            your tables to <literal>InnoDB</literal>. See
-            <xref linkend="innodb"/>.
-          </para>
-
-          <formalpara role="mnmas">
-
-            <title>MySQL Enterprise</title>
-
-            <para>
-              Lock contention can seriously degrade performance. The
-              MySQL Enterprise Monitor provides expert advice on
-              avoiding this problem. To subscribe, see
-              &base-url-enterprise;advisors.html.
-            </para>
-
-          </formalpara>
-        </listitem>
-
-      </itemizedlist>
-
-    </section>
-
-    <section id="concurrent-inserts">
-
-      <title>Concurrent Inserts</title>
-
-      <indexterm>
-        <primary>concurrent inserts</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>inserts</primary>
-        <secondary>concurrent</secondary>
-      </indexterm>
-
-      <para>
-        The <literal>MyISAM</literal> storage engine supports concurrent
-        inserts to reduce contention between readers and writers for a
-        given table: If a <literal>MyISAM</literal> table has no holes
-        in the data file (deleted rows in the middle), an
-        <literal role="stmt">INSERT</literal> statement can be executed
-        to add rows to the end of the table at the same time that
-        <literal role="stmt">SELECT</literal> statements are reading
-        rows from the table. If there are multiple
-        <literal role="stmt">INSERT</literal> statements, they are
-        queued and performed in sequence, concurrently with the
-        <literal role="stmt">SELECT</literal> statements. The results of
-        a concurrent <literal role="stmt">INSERT</literal> may not be
-        visible immediately.
-      </para>
-
-      <para>
-        The <literal role="sysvar">concurrent_insert</literal> system
-        variable can be set to modify the concurrent-insert processing.
-        By default, the variable is set to <literal>AUTO</literal> (or
-        1) and concurrent inserts are handled as just described. If
-        <literal role="sysvar">concurrent_insert</literal> is set to
-        <literal>NEVER</literal> (or 0), concurrent inserts are
-        disabled. If the variable is set to <literal>ALWAYS</literal>
-        (or 2), concurrent inserts at the end of the table are allowed
-        even for tables that have deleted rows. See also the description
-        of the
-        <link linkend="sysvar_concurrent_insert"><literal role="sysvar">concurrent_insert</literal></link>
-        system variable.
-      </para>
-
-      <para>
-        Under circumstances where concurrent inserts can be used, there
-        is seldom any need to use the <literal>DELAYED</literal>
-        modifier for <literal role="stmt">INSERT</literal> statements.
-        See <xref linkend="insert-delayed"/>.
-      </para>
-
-      <para>
-        If you are using the binary log, concurrent inserts are
-        converted to normal inserts for <literal>CREATE ...
-        SELECT</literal> or
-        <literal role="stmt" condition="insert-select">INSERT ...
-        SELECT</literal> statements. This is done to ensure that you can
-        re-create an exact copy of your tables by applying the log
-        during a backup operation. See <xref linkend="binary-log"/>. In
-        addition, for those statements a read lock is placed on the
-        selected-from table such that inserts into that table are
-        blocked. The effect is that concurrent inserts for that table
-        must wait as well.
-      </para>
-
-      <para>
-        With <literal role="stmt" condition="load-data">LOAD DATA
-        INFILE</literal>, if you specify <literal>CONCURRENT</literal>
-        with a <literal>MyISAM</literal> table that satisfies the
-        condition for concurrent inserts (that is, it contains no free
-        blocks in the middle), other sessions can retrieve data from the
-        table while <literal role="stmt">LOAD DATA</literal> is
-        executing. Use of the <literal>CONCURRENT</literal> option
-        affects the performance of <literal role="stmt">LOAD
-        DATA</literal> a bit, even if no other session is using the
-        table at the same time.
-      </para>
-
-      <para>
-        If you specify <literal>HIGH_PRIORITY</literal>, it overrides
-        the effect of the
-        <option role="mysqld">--low-priority-updates</option> option if
-        the server was started with that option. It also causes
-        concurrent inserts not to be used.
-      </para>
-
-      <para>
-        For <literal role="stmt" condition="lock-tables">LOCK
-        TABLE</literal>, the difference between <literal>READ
-        LOCAL</literal> and <literal>READ</literal> is that
-        <literal>READ LOCAL</literal> permits nonconflicting
-        <literal role="stmt">INSERT</literal> statements (concurrent
-        inserts) to execute while the lock is held. However, this cannot
-        be used if you are going to manipulate the database using
-        processes external to the server while you hold the lock.
-      </para>
-
-    </section>
-
-    <section id="metadata-locking">
-
-      <title>Metadata Locking Within Transactions</title>
-
-      <indexterm>
-        <primary>metadata locking</primary>
-        <secondary>transactions</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>transactions</primary>
-        <secondary>metadata locking</secondary>
-      </indexterm>
-
-      <para>
-        To ensure transaction serializability, the server must not allow
-        one session to perform a data definition language (DDL)
-        statement on a table that is used in an uncompleted transaction
-        in another session.
-      </para>
-
-      <para>
-        As of MySQL 6.0.11, the server achieves this by acquiring
-        metadata locks on tables used within a transaction and deferring
-        release of those locks until the transaction ends. A metadata
-        lock on a table prevents changes to the table's structure. This
-        locking approach has the implication that a table that is being
-        used by a transaction within one session cannot be used in DDL
-        statements by other sessions until the transaction ends. For
-        example, if a table <literal>t1</literal> is in use by a
-        transaction, another session that attempts to execute
-        <literal role="stmt" condition="drop-table">DROP TABLE
-        t1</literal> will block until the transaction ends.
-      </para>
-
-      <para>
-        If the server acquires metadata locks for a statement that is
-        syntactically valid but fails during execution, it does not
-        release the locks early. Lock release is still deferred to the
-        end of the transaction because the failed statement is written
-        to the binary log and the locks protect log consistency.
-      </para>
-
-      <para>
-        Metadata locks acquired during a
-        <literal role="stmt">PREPARE</literal> statement are released
-        once the statement has been prepared, even if preparation occurs
-        within a multiple-statement transaction.
-      </para>
-
-      <para>
-        Before MySQL 6.0.11, when a transaction acquired a metadata lock
-        for a table used within a statement, it released the lock at the
-        end of the statement. This approach had the disadvantage that if
-        a DDL statement occurred for a table that was being used by
-        another session in an active transaction, statements could be
-        written to the binary log in the wrong order.
-      </para>
-
-    </section>
-
-    <section id="external-locking">
-
-      <title>External Locking</title>
-
-      <indexterm>
-        <primary>external locking</primary>
-      </indexterm>
-
-      <indexterm>
-        <primary>locking</primary>
-        <secondary>external</secondary>
-      </indexterm>
-
-      <para>
-        External locking is the use of file system locking to manage
-        contention for database tables by multiple processes. External
-        locking is used in situations where a single process such as the
-        MySQL server cannot be assumed to be the only process that
-        requires access to tables. Here are some examples:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            If you run multiple servers that use the same database
-            directory (not recommended), each server must have external
-            locking enabled.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If you use <command>myisamchk</command> to perform table
-            maintenance operations on <literal>MyISAM</literal> tables,
-            you must either ensure that the server is not running, or
-            that the server has external locking enabled so that it
-            locks table files as necessary to coordinate with
-            <command>myisamchk</command> for access to the tables. The
-            same is true for use of <command>myisampack</command> to
-            pack <literal>MyISAM</literal> tables.
-          </para>
-
-          <para>
-            If the server is run with external locking enabled, you can
-            use <command>myisamchk</command> at any time for read
-            operations such a checking tables. In this case, if the
-            server tries to update a table that
-            <command>myisamchk</command> is using, the server will wait
-            for <command>myisamchk</command> to finish before it
-            continues.
-          </para>
-
-          <para>
-            If you use <command>myisamchk</command> for write operations
-            such as repairing or optimizing tables, or if you use
-            <command>myisampack</command> to pack tables, you
-            <emphasis>must</emphasis> always ensure that the
-            <command>mysqld</command> server is not using the table. If
-            you don't stop <command>mysqld</command>, you should at
-            least do a <command>mysqladmin flush-tables</command> before
-            you run <command>myisamchk</command>. Your tables
-            <emphasis>may become corrupted</emphasis> if the server and
-            <command>myisamchk</command> access the tables
-            simultaneously.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        With external locking in effect, each process that requires
-        access to a table acquires a file system lock for the table
-        files before proceeding to access the table. If all necessary
-        locks cannot be acquired, the process is blocked from accessing
-        the table until the locks can be obtained (after the process
-        that currently holds the locks releases them).
-      </para>
-
-      <para>
-        External locking affects server performance because the server
-        must sometimes wait for other processes before it can access
-        tables.
-      </para>
-
-      <para>
-        External locking is unnecessary if you run a single server to
-        access a given data directory (which is the usual case) and if
-        no other programs such as <command>myisamchk</command> need to
-        modify tables while the server is running. If you only
-        <emphasis>read</emphasis> tables with other programs, external
-        locking is not required, although <command>myisamchk</command>
-        might report warnings if the server changes tables while
-        <command>myisamchk</command> is reading them.
-      </para>
-
-      <para>
-        With external locking disabled, to use
-        <command>myisamchk</command>, you must either stop the server
-        while <command>myisamchk</command> executes or else lock and
-        flush the tables before running <command>myisamchk</command>.
-        (See <xref linkend="system-optimization"/>.) To avoid this
-        requirement, use the <literal role="stmt">CHECK TABLE</literal>
-        and <literal role="stmt">REPAIR TABLE</literal> statements to
-        check and repair <literal>MyISAM</literal> tables.
-      </para>
-
-      <para>
-        For <command>mysqld</command>, external locking is controlled by
-        the value of the
-        <literal role="sysvar">skip_external_locking</literal> system
-        variable. When this variable is enabled, external locking is
-        disabled, and vice versa. From MySQL 4.0 on, external locking is
-        disabled by default. Before MySQL 4.0, external locking is
-        enabled by default on Linux or when MySQL is configured to use
-        MIT-pthreads.
-      </para>
-
-      <para>
-        Use of external locking can be controlled at server startup by
-        using the <option role="mysqld">--external-locking</option> or
-        <option role="mysqld">--skip-external-locking</option> option.
-      </para>
-
-      <para>
-        If you do use external locking option to enable updates to
-        <literal>MyISAM</literal> tables from many MySQL processes, you
-        must ensure that the following conditions are satisfied:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            You should not use the query cache for queries that use
-            tables that are updated by another process.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            You should not start the server with the
-            <option role="mysqld">--delay-key-write=ALL</option> option
-            or use the <literal>DELAY_KEY_WRITE=1</literal> table option
-            for any shared tables. Otherwise, index corruption can
-            occur.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-      <para>
-        The easiest way to satisfy these conditions is to always use
-        <option role="mysqld">--external-locking</option> together with
-        <option role="mysqld">--delay-key-write=OFF</option> and
-        <option role="sysvar">--query-cache-size=0</option>. (This is
-        not done by default because in many setups it is useful to have
-        a mixture of the preceding options.)
-      </para>
-
-    </section>
-
-  </section>
-
-  <section id="optimizing-database-structure">
-
-    <title>Optimizing Database Structure</title>
-
-    <section id="data-size">
-
-      <title>Make Your Data as Small as Possible</title>
-
-      <indexterm>
-        <primary>data</primary>
-        <secondary>size</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>reducing</primary>
-        <secondary>data size</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>storage space</primary>
-        <secondary>minimizing</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>tables</primary>
-        <secondary>improving performance</secondary>
-      </indexterm>
-
-      <indexterm>
-        <primary>performance</primary>
-        <secondary>improving</secondary>
-      </indexterm>
-
-      <para>
-        One of the most basic optimizations is to design your tables to
-        take as little space on the disk as possible. This can result in
-        huge improvements because disk reads are faster, and smaller
-        tables normally require less main memory while their contents
-        are being actively processed during query execution. Indexing
-        also is a lesser resource burden if done on smaller columns.
-      </para>
-
-      <para>
-        MySQL supports many different storage engines (table types) and
-        row formats. For each table, you can decide which storage and
-        indexing method to use. Choosing the proper table format for
-        your application may give you a big performance gain. See
-        <xref linkend="storage-engines"/>.
-      </para>
-
-      <para>
-        You can get better performance for a table and minimize storage
-        space by using the techniques listed here:
-      </para>
-
-      <itemizedlist>
-
-        <listitem>
-          <para>
-            Use the most efficient (smallest) data types possible. MySQL
-            has many specialized types that save disk space and memory.
-            For example, use the smaller integer types if possible to
-            get smaller tables. <literal role="type">MEDIUMINT</literal>
-            is often a better choice than
-            <literal role="type">INT</literal> because a
-            <literal role="type">MEDIUMINT</literal> column uses 25%
-            less space.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Declare columns to be <literal>NOT NULL</literal> if
-            possible. It makes everything faster and you save one bit
-            per column. If you really need <literal>NULL</literal> in
-            your application, you should definitely use it. Just avoid
-            having it on all columns by default.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            For <literal>MyISAM</literal> tables, if you do not have any
-            variable-length columns
-            (<literal role="type">VARCHAR</literal>,
-            <literal role="type">TEXT</literal>, or
-            <literal role="type">BLOB</literal> columns), a fixed-size
-            row format is used. This is faster but unfortunately may
-            waste some space. See
-            <xref linkend="myisam-table-formats"/>. You can hint that
-            you want to have fixed length rows even if you have
-            <literal role="type">VARCHAR</literal> columns with the
-            <literal role="stmt">CREATE TABLE</literal> option
-            <literal>ROW_FORMAT=FIXED</literal>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            <literal>InnoDB</literal> tables use a compact storage
-            format. In versions of MySQL earlier than 5.0.3,
-            <literal>InnoDB</literal> rows contain some redundant
-            information, such as the number of columns and the length of
-            each column, even for fixed-size columns. By default, tables
-            are created in the compact format
-            (<literal>ROW_FORMAT=COMPACT</literal>). If you wish to
-            downgrade to older versions of MySQL, you can request the
-            old format with <literal>ROW_FORMAT=REDUNDANT</literal>.
-          </para>
-
-          <para>
-            The presence of the compact row format decreases row storage
-            space by about 20% at the cost of increasing CPU use for
-            some operations. If your workload is a typical one that is
-            limited by cache hit rates and disk speed it is likely to be
-            faster. If it is a rare case that is limited by CPU speed,
-            it might be slower.
-          </para>
-
-          <para>
-            The compact <literal>InnoDB</literal> format also changes
-            how <literal role="type">CHAR</literal> columns containing
-            UTF-8 data are stored. With
-            <literal>ROW_FORMAT=REDUNDANT</literal>, a UTF-8
-            <literal>CHAR(<replaceable>N</replaceable>)</literal>
-            occupies 3 &times; <replaceable>N</replaceable> bytes, given
-            that the maximum length of a UTF-8 encoded character is
-            three bytes. Many languages can be written primarily using
-            single-byte UTF-8 characters, so a fixed storage length
-            often wastes space. With
-            <literal>ROW_FORMAT=COMPACT</literal> format,
-            <literal>InnoDB</literal> allocates a variable amount of
-            storage in the range from <replaceable>N</replaceable> to 3
-            &times; <replaceable>N</replaceable> bytes for these columns
-            by stripping trailing spaces if necessary. The minimum
-            storage length is kept as <replaceable>N</replaceable> bytes
-            to facilitate in-place updates in typical cases.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            The primary index of a table should be as short as possible.
-            This makes identification of each row easy and efficient.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            Create only the indexes that you really need. Indexes are
-            good for retrieval but bad when you need to store data
-            quickly. If you access a table mostly by searching on a
-            combination of columns, create an index on them. The first
-            part of the index should be the column most used. If you
-            <emphasis>always</emphasis> use many columns when selecting
-            from the table, the first column in the index should be the
-            one with the most duplicates to obtain better compression of
-            the index.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            If it is very likely that a string column has a unique
-            prefix on the first number of characters, it is better to
-            index only this prefix, using MySQL's support for creating
-            an index on the leftmost part of the column (see
-            <xref linkend="create-index"/>). Shorter indexes are faster,
-            not only because they require less disk space, but because
-            they also give you more hits in the index cache, and thus
-            fewer disk seeks. See <xref linkend="server-parameters"/>.
-          </para>
-        </listitem>
-
-        <listitem>
-          <para>
-            In some circumstances, it can be beneficial to split into
-            two a table that is scanned very often. This is especially
-            true if it is a dynamic-format table and it is possible to
-            use a smaller static format table that can be used to find
-            the relevant rows when scanning the table.
-          </para>
-        </listitem>
-
-      </itemizedlist>
-
-    </section>
-
-    <section id="indexes">
-
       <title>Column Indexes</title>
 
       <indexterm>

@@ -11247,7 +10063,7 @@
         MySQL can create composite indexes (that is, indexes on multiple
         columns). An index may consist of up to 16 columns. For certain
         data types, you can index a prefix of the column (see
-        <xref linkend="indexes"/>).
+        <xref linkend="column-indexes"/>).
       </para>
 
       <para>

@@ -12756,6 +11572,1196 @@
 
     </section>
 
+  </section>
+
+  <section id="locking-issues">
+
+    <title>Locking Issues</title>
+
+    <para>
+      MySQL manages contention for table contents using locking:
+    </para>
+
+    <itemizedlist>
+
+      <listitem>
+        <para>
+          Internal locking is performed within the MySQL server itself
+          to manage contention for table contents by multiple threads.
+          This type of locking is internal because it is performed
+          entirely by the server and involves no other programs. See
+          <xref linkend="internal-locking"/>.
+        </para>
+      </listitem>
+
+      <listitem>
+        <para>
+          External locking occurs when the server and other programs
+          lock table files to coordinate among themselves which program
+          can access the tables at which time. See
+          <xref linkend="external-locking"/>.
+        </para>
+      </listitem>
+
+    </itemizedlist>
+
+    <section id="internal-locking">
+
+      <title>Internal Locking Methods</title>
+
+      <indexterm>
+        <primary>internal locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>internal</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking methods</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>methods</primary>
+        <secondary>locking</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>row-level locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>table-level locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>row-level</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>table-level</secondary>
+      </indexterm>
+
+      <para>
+        This section discusses internal locking; that is, locking
+        performed within the MySQL server itself to manage contention
+        for table contents by multiple sessions. This type of locking is
+        internal because it is performed entirely by the server and
+        involves no other programs. External locking occurs when the
+        server and other programs lock table files to coordinate among
+        themselves which program can access the tables at which time.
+        See <xref linkend="external-locking"/>.
+      </para>
+
+      <para>
+        MySQL uses table-level locking for <literal>MyISAM</literal>,
+        <literal>MEMORY</literal>, and <literal>MERGE</literal> tables,
+        and row-level locking for <literal>InnoDB</literal> tables.
+      </para>
+
+      <para>
+        In many cases, you can make an educated guess about which
+        locking type is best for an application, but generally it is
+        difficult to say that a given lock type is better than another.
+        Everything depends on the application and different parts of an
+        application may require different lock types.
+      </para>
+
+      <para>
+        To decide whether you want to use a storage engine with
+        row-level locking, you should look at what your application does
+        and what mix of select and update statements it uses. For
+        example, most Web applications perform many selects, relatively
+        few deletes, updates based mainly on key values, and inserts
+        into a few specific tables. The base MySQL
+        <literal>MyISAM</literal> setup is very well tuned for this.
+      </para>
+
+      <formalpara role="mnmas">
+
+        <title>MySQL Enterprise</title>
+
+        <para>
+          The MySQL Enterprise Monitor provides expert advice on when to
+          use table-level locking and when to use row-level locking. To
+          subscribe, see &base-url-enterprise;advisors.html.
+        </para>
+
+      </formalpara>
+
+      <para>
+        Table locking in MySQL is deadlock-free for storage engines that
+        use table-level locking. Deadlock avoidance is managed by always
+        requesting all needed locks at once at the beginning of a query
+        and always locking the tables in the same order.
+      </para>
+
+      <para>
+        MySQL grants table write locks as follows:
+      </para>
+
+      <orderedlist>
+
+        <listitem>
+          <para>
+            If there are no locks on the table, put a write lock on it.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Otherwise, put the lock request in the write lock queue.
+          </para>
+        </listitem>
+
+      </orderedlist>
+
+      <para>
+        MySQL grants table read locks as follows:
+      </para>
+
+      <orderedlist>
+
+        <listitem>
+          <para>
+            If there are no write locks on the table, put a read lock on
+            it.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Otherwise, put the lock request in the read lock queue.
+          </para>
+        </listitem>
+
+      </orderedlist>
+
+      <para>
+        Table updates are given higher priority than table retrievals.
+        Therefore, when a lock is released, the lock is made available
+        to the requests in the write lock queue and then to the requests
+        in the read lock queue. This ensures that updates to a table are
+        not <quote>starved</quote> even if there is heavy
+        <literal role="stmt">SELECT</literal> activity for the table.
+        However, if you have many updates for a table,
+        <literal role="stmt">SELECT</literal> statements wait until
+        there are no more updates.
+      </para>
+
+      <para>
+        For information on altering the priority of reads and writes,
+        see <xref linkend="table-locking"/>.
+      </para>
+
+      <para>
+        You can analyze the table lock contention on your system by
+        checking the
+        <literal role="statvar">Table_locks_immediate</literal> and
+        <literal role="statvar">Table_locks_waited</literal> status
+        variables, which indicate the number of times that requests for
+        table locks could be granted immediately and the number that had
+        to wait, respectively:
+      </para>
+
+<programlisting>
+mysql&gt; <userinput>SHOW STATUS LIKE 'Table%';</userinput>
++-----------------------+---------+
+| Variable_name         | Value   |
++-----------------------+---------+
+| Table_locks_immediate | 1151552 |
+| Table_locks_waited    | 15324   |
++-----------------------+---------+
+</programlisting>
+
+      <indexterm>
+        <primary>concurrent inserts</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>inserts</primary>
+        <secondary>concurrent</secondary>
+      </indexterm>
+
+      <para>
+        The <literal>MyISAM</literal> storage engine supports concurrent
+        inserts to reduce contention between readers and writers for a
+        given table: If a <literal>MyISAM</literal> table has no free
+        blocks in the middle of the data file, rows are always inserted
+        at the end of the data file. In this case, you can freely mix
+        concurrent <literal role="stmt">INSERT</literal> and
+        <literal role="stmt">SELECT</literal> statements for a
+        <literal>MyISAM</literal> table without locks. That is, you can
+        insert rows into a <literal>MyISAM</literal> table at the same
+        time other clients are reading from it. Holes can result from
+        rows having been deleted from or updated in the middle of the
+        table. If there are holes, concurrent inserts are disabled but
+        are enabled again automatically when all holes have been filled
+        with new data.. This behavior is altered by the
+        <literal role="sysvar">concurrent_insert</literal> system
+        variable. See <xref linkend="concurrent-inserts"/>.
+      </para>
+
+      <para>
+        If you acquire a table lock explicitly with
+        <literal role="stmt">LOCK TABLES</literal>, you can request a
+        <literal>READ LOCAL</literal> lock rather than a
+        <literal>READ</literal> lock to enable other sessions to perform
+        concurrent inserts while you have the table locked.
+      </para>
+
+      <para>
+        To perform many <literal role="stmt">INSERT</literal> and
+        <literal role="stmt">SELECT</literal> operations on a table
+        <literal>real_table</literal> when concurrent inserts are not
+        possible, you can insert rows into a temporary table
+        <literal>temp_table</literal> and update the real table with the
+        rows from the temporary table periodically. This can be done
+        with the following code:
+      </para>
+
+<programlisting>
+mysql&gt; <userinput>LOCK TABLES real_table WRITE, temp_table WRITE;</userinput>
+mysql&gt; <userinput>INSERT INTO real_table SELECT * FROM temp_table;</userinput>
+mysql&gt; <userinput>DELETE FROM temp_table;</userinput>
+mysql&gt; <userinput>UNLOCK TABLES;</userinput>
+</programlisting>
+
+      <para>
+        <literal>InnoDB</literal> uses row locks. Deadlocks are possible
+        for <literal>InnoDB</literal> because it automatically acquires
+        locks during the processing of SQL statements, not at the start
+        of the transaction.
+      </para>
+
+      <para>
+        Advantages of row-level locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Fewer lock conflicts when different sessions access
+            different rows
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Fewer changes for rollbacks
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Possible to lock a single row for a long time
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Disadvantages of row-level locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Requires more memory than table-level locks
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Slower than table-level locks when used on a large part of
+            the table because you must acquire many more locks
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Slower than other locks if you often do <literal>GROUP
+            BY</literal> operations on a large part of the data or if
+            you must scan the entire table frequently
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Generally, table locks are superior to row-level locks in the
+        following cases:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Most statements for the table are reads
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Statements for the table are a mix of reads and writes,
+            where writes are updates or deletes for a single row that
+            can be fetched with one key read:
+          </para>
+
+<programlisting>
+UPDATE <replaceable>tbl_name</replaceable> SET <replaceable>column</replaceable>=<replaceable>value</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
+DELETE FROM <replaceable>tbl_name</replaceable> WHERE <replaceable>unique_key_col</replaceable>=<replaceable>key_value</replaceable>;
+</programlisting>
+        </listitem>
+
+        <listitem>
+          <para>
+            <literal role="stmt">SELECT</literal> combined with
+            concurrent <literal role="stmt">INSERT</literal> statements,
+            and very few <literal role="stmt">UPDATE</literal> or
+            <literal role="stmt">DELETE</literal> statements
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Many scans or <literal>GROUP BY</literal> operations on the
+            entire table without any writers
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        With higher-level locks, you can more easily tune applications
+        by supporting locks of different types, because the lock
+        overhead is less than for row-level locks.
+      </para>
+
+      <para>
+        Options other than row-level locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Versioning (such as that used in MySQL for concurrent
+            inserts) where it is possible to have one writer at the same
+            time as many readers. This means that the database or table
+            supports different views for the data depending on when
+            access begins. Other common terms for this are <quote>time
+            travel,</quote> <quote>copy on write,</quote> or <quote>copy
+            on demand.</quote>
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Copy on demand is in many cases superior to row-level
+            locking. However, in the worst case, it can use much more
+            memory than using normal locks.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Instead of using row-level locks, you can employ
+            application-level locks, such as those provided by
+            <literal role="func">GET_LOCK()</literal> and
+            <literal role="func">RELEASE_LOCK()</literal> in MySQL.
+            These are advisory locks, so they work only with
+            applications that cooperate with each other. See
+            <xref linkend="miscellaneous-functions"/>.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+    </section>
+
+    <section id="table-locking">
+
+      <title>Table Locking Issues</title>
+
+      <indexterm>
+        <primary>problems</primary>
+        <secondary>table locking</secondary>
+      </indexterm>
+
+      <para>
+        To achieve a very high lock speed, MySQL uses table locking
+        (instead of page, row, or column locking) for all storage
+        engines except <literal>InnoDB</literal>.
+      </para>
+
+      <para>
+        For <literal>InnoDB</literal> tables, MySQL uses table locking
+        only if you explicitly lock the table with
+        <literal role="stmt">LOCK TABLES</literal>. For this storage
+        engine, avoid using <literal role="stmt">LOCK TABLES</literal>
+        at all, because <literal>InnoDB</literal> uses automatic
+        row-level locking to ensure transaction isolation.
+      </para>
+
+      <para>
+        For large tables, table locking is often better than row
+        locking, but there are some disadvantages:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Table locking enables many sessions to read from a table at
+            the same time, but if a session wants to write to a table,
+            it must first get exclusive access. During the update, all
+            other sessions that want to access this particular table
+            must wait until the update is done.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Table locking causes problems in cases such as when a
+            session is waiting because the disk is full and free space
+            needs to become available before the session can proceed. In
+            this case, all sessions that want to access the problem
+            table are also put in a waiting state until more disk space
+            is made available.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Table locking is also disadvantageous under the following
+        scenario:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            A session issues a <literal role="stmt">SELECT</literal>
+            that takes a long time to run.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Another session then issues an
+            <literal role="stmt">UPDATE</literal> on the same table.
+            This session waits until the
+            <literal role="stmt">SELECT</literal> is finished.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Another session issues another
+            <literal role="stmt">SELECT</literal> statement on the same
+            table. Because <literal role="stmt">UPDATE</literal> has
+            higher priority than <literal role="stmt">SELECT</literal>,
+            this <literal role="stmt">SELECT</literal> waits for the
+            <literal role="stmt">UPDATE</literal> to finish,
+            <emphasis>after</emphasis> waiting for the first
+            <literal role="stmt">SELECT</literal> to finish.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        The following items describe some ways to avoid or reduce
+        contention caused by table locking:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Try to get the <literal role="stmt">SELECT</literal>
+            statements to run faster so that they lock tables for a
+            shorter time. You might have to create some summary tables
+            to do this.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Start <command>mysqld</command> with
+            <option role="mysqld">--low-priority-updates</option>. For
+            storage engines that use only table-level locking (such as
+            <literal>MyISAM</literal>, <literal>MEMORY</literal>, and
+            <literal>MERGE</literal>), this gives all statements that
+            update (modify) a table lower priority than
+            <literal role="stmt">SELECT</literal> statements. In this
+            case, the second <literal role="stmt">SELECT</literal>
+            statement in the preceding scenario would execute before the
+            <literal role="stmt">UPDATE</literal> statement, and would
+            not need to wait for the first
+            <literal role="stmt">SELECT</literal> to finish.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            To specify that all updates issued in a specific connection
+            should be done with low priority, set the
+            <literal role="sysvar">low_priority_updates</literal> server
+            system variable equal to 1.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            To give a specific <literal role="stmt">INSERT</literal>,
+            <literal role="stmt">UPDATE</literal>, or
+            <literal role="stmt">DELETE</literal> statement lower
+            priority, use the <literal>LOW_PRIORITY</literal> attribute.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            To give a specific <literal role="stmt">SELECT</literal>
+            statement higher priority, use the
+            <literal>HIGH_PRIORITY</literal> attribute. See
+            <xref linkend="select"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Start <command>mysqld</command> with a low value for the
+            <literal role="sysvar">max_write_lock_count</literal> system
+            variable to force MySQL to temporarily elevate the priority
+            of all <literal role="stmt">SELECT</literal> statements that
+            are waiting for a table after a specific number of inserts
+            to the table occur. This permits <literal>READ</literal>
+            locks after a certain number of <literal>WRITE</literal>
+            locks.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you have problems with
+            <literal role="stmt">INSERT</literal> combined with
+            <literal role="stmt">SELECT</literal>, consider switching to
+            <literal>MyISAM</literal> tables, which support concurrent
+            <literal role="stmt">SELECT</literal> and
+            <literal role="stmt">INSERT</literal> statements. (See
+            <xref linkend="concurrent-inserts"/>.)
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you mix inserts and deletes on the same table,
+            <literal role="stmt">INSERT DELAYED</literal> may be of
+            great help. See <xref linkend="insert-delayed"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you have problems with mixed
+            <literal role="stmt">SELECT</literal> and
+            <literal role="stmt">DELETE</literal> statements, the
+            <literal>LIMIT</literal> option to
+            <literal role="stmt">DELETE</literal> may help. See
+            <xref linkend="delete"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Using <literal>SQL_BUFFER_RESULT</literal> with
+            <literal role="stmt">SELECT</literal> statements can help to
+            make the duration of table locks shorter. See
+            <xref linkend="select"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            You could change the locking code in
+            <filename>mysys/thr_lock.c</filename> to use a single queue.
+            In this case, write locks and read locks would have the same
+            priority, which might help some applications.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        Here are some tips concerning table locks in MySQL:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Concurrent users are not a problem if you do not mix updates
+            with selects that need to examine many rows in the same
+            table.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            You can use <literal role="stmt">LOCK TABLES</literal> to
+            increase speed, because many updates within a single lock is
+            much faster than updating without locks. Splitting table
+            contents into separate tables may also help.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you encounter speed problems with table locks in MySQL,
+            you may be able to improve performance by converting some of
+            your tables to <literal>InnoDB</literal>. See
+            <xref linkend="innodb"/>.
+          </para>
+
+          <formalpara role="mnmas">
+
+            <title>MySQL Enterprise</title>
+
+            <para>
+              Lock contention can seriously degrade performance. The
+              MySQL Enterprise Monitor provides expert advice on
+              avoiding this problem. To subscribe, see
+              &base-url-enterprise;advisors.html.
+            </para>
+
+          </formalpara>
+        </listitem>
+
+      </itemizedlist>
+
+    </section>
+
+    <section id="concurrent-inserts">
+
+      <title>Concurrent Inserts</title>
+
+      <indexterm>
+        <primary>concurrent inserts</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>inserts</primary>
+        <secondary>concurrent</secondary>
+      </indexterm>
+
+      <para>
+        The <literal>MyISAM</literal> storage engine supports concurrent
+        inserts to reduce contention between readers and writers for a
+        given table: If a <literal>MyISAM</literal> table has no holes
+        in the data file (deleted rows in the middle), an
+        <literal role="stmt">INSERT</literal> statement can be executed
+        to add rows to the end of the table at the same time that
+        <literal role="stmt">SELECT</literal> statements are reading
+        rows from the table. If there are multiple
+        <literal role="stmt">INSERT</literal> statements, they are
+        queued and performed in sequence, concurrently with the
+        <literal role="stmt">SELECT</literal> statements. The results of
+        a concurrent <literal role="stmt">INSERT</literal> may not be
+        visible immediately.
+      </para>
+
+      <para>
+        The <literal role="sysvar">concurrent_insert</literal> system
+        variable can be set to modify the concurrent-insert processing.
+        By default, the variable is set to <literal>AUTO</literal> (or
+        1) and concurrent inserts are handled as just described. If
+        <literal role="sysvar">concurrent_insert</literal> is set to
+        <literal>NEVER</literal> (or 0), concurrent inserts are
+        disabled. If the variable is set to <literal>ALWAYS</literal>
+        (or 2), concurrent inserts at the end of the table are allowed
+        even for tables that have deleted rows. See also the description
+        of the
+        <link linkend="sysvar_concurrent_insert"><literal role="sysvar">concurrent_insert</literal></link>
+        system variable.
+      </para>
+
+      <para>
+        Under circumstances where concurrent inserts can be used, there
+        is seldom any need to use the <literal>DELAYED</literal>
+        modifier for <literal role="stmt">INSERT</literal> statements.
+        See <xref linkend="insert-delayed"/>.
+      </para>
+
+      <para>
+        If you are using the binary log, concurrent inserts are
+        converted to normal inserts for <literal>CREATE ...
+        SELECT</literal> or
+        <literal role="stmt" condition="insert-select">INSERT ...
+        SELECT</literal> statements. This is done to ensure that you can
+        re-create an exact copy of your tables by applying the log
+        during a backup operation. See <xref linkend="binary-log"/>. In
+        addition, for those statements a read lock is placed on the
+        selected-from table such that inserts into that table are
+        blocked. The effect is that concurrent inserts for that table
+        must wait as well.
+      </para>
+
+      <para>
+        With <literal role="stmt" condition="load-data">LOAD DATA
+        INFILE</literal>, if you specify <literal>CONCURRENT</literal>
+        with a <literal>MyISAM</literal> table that satisfies the
+        condition for concurrent inserts (that is, it contains no free
+        blocks in the middle), other sessions can retrieve data from the
+        table while <literal role="stmt">LOAD DATA</literal> is
+        executing. Use of the <literal>CONCURRENT</literal> option
+        affects the performance of <literal role="stmt">LOAD
+        DATA</literal> a bit, even if no other session is using the
+        table at the same time.
+      </para>
+
+      <para>
+        If you specify <literal>HIGH_PRIORITY</literal>, it overrides
+        the effect of the
+        <option role="mysqld">--low-priority-updates</option> option if
+        the server was started with that option. It also causes
+        concurrent inserts not to be used.
+      </para>
+
+      <para>
+        For <literal role="stmt" condition="lock-tables">LOCK
+        TABLE</literal>, the difference between <literal>READ
+        LOCAL</literal> and <literal>READ</literal> is that
+        <literal>READ LOCAL</literal> permits nonconflicting
+        <literal role="stmt">INSERT</literal> statements (concurrent
+        inserts) to execute while the lock is held. However, this cannot
+        be used if you are going to manipulate the database using
+        processes external to the server while you hold the lock.
+      </para>
+
+    </section>
+
+    <section id="metadata-locking">
+
+      <title>Metadata Locking Within Transactions</title>
+
+      <indexterm>
+        <primary>metadata locking</primary>
+        <secondary>transactions</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>transactions</primary>
+        <secondary>metadata locking</secondary>
+      </indexterm>
+
+      <para>
+        To ensure transaction serializability, the server must not allow
+        one session to perform a data definition language (DDL)
+        statement on a table that is used in an uncompleted transaction
+        in another session.
+      </para>
+
+      <para>
+        As of MySQL 6.0.11, the server achieves this by acquiring
+        metadata locks on tables used within a transaction and deferring
+        release of those locks until the transaction ends. A metadata
+        lock on a table prevents changes to the table's structure. This
+        locking approach has the implication that a table that is being
+        used by a transaction within one session cannot be used in DDL
+        statements by other sessions until the transaction ends. For
+        example, if a table <literal>t1</literal> is in use by a
+        transaction, another session that attempts to execute
+        <literal role="stmt" condition="drop-table">DROP TABLE
+        t1</literal> will block until the transaction ends.
+      </para>
+
+      <para>
+        If the server acquires metadata locks for a statement that is
+        syntactically valid but fails during execution, it does not
+        release the locks early. Lock release is still deferred to the
+        end of the transaction because the failed statement is written
+        to the binary log and the locks protect log consistency.
+      </para>
+
+      <para>
+        Metadata locks acquired during a
+        <literal role="stmt">PREPARE</literal> statement are released
+        once the statement has been prepared, even if preparation occurs
+        within a multiple-statement transaction.
+      </para>
+
+      <para>
+        Before MySQL 6.0.11, when a transaction acquired a metadata lock
+        for a table used within a statement, it released the lock at the
+        end of the statement. This approach had the disadvantage that if
+        a DDL statement occurred for a table that was being used by
+        another session in an active transaction, statements could be
+        written to the binary log in the wrong order.
+      </para>
+
+    </section>
+
+    <section id="external-locking">
+
+      <title>External Locking</title>
+
+      <indexterm>
+        <primary>external locking</primary>
+      </indexterm>
+
+      <indexterm>
+        <primary>locking</primary>
+        <secondary>external</secondary>
+      </indexterm>
+
+      <para>
+        External locking is the use of file system locking to manage
+        contention for database tables by multiple processes. External
+        locking is used in situations where a single process such as the
+        MySQL server cannot be assumed to be the only process that
+        requires access to tables. Here are some examples:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            If you run multiple servers that use the same database
+            directory (not recommended), each server must have external
+            locking enabled.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If you use <command>myisamchk</command> to perform table
+            maintenance operations on <literal>MyISAM</literal> tables,
+            you must either ensure that the server is not running, or
+            that the server has external locking enabled so that it
+            locks table files as necessary to coordinate with
+            <command>myisamchk</command> for access to the tables. The
+            same is true for use of <command>myisampack</command> to
+            pack <literal>MyISAM</literal> tables.
+          </para>
+
+          <para>
+            If the server is run with external locking enabled, you can
+            use <command>myisamchk</command> at any time for read
+            operations such a checking tables. In this case, if the
+            server tries to update a table that
+            <command>myisamchk</command> is using, the server will wait
+            for <command>myisamchk</command> to finish before it
+            continues.
+          </para>
+
+          <para>
+            If you use <command>myisamchk</command> for write operations
+            such as repairing or optimizing tables, or if you use
+            <command>myisampack</command> to pack tables, you
+            <emphasis>must</emphasis> always ensure that the
+            <command>mysqld</command> server is not using the table. If
+            you don't stop <command>mysqld</command>, you should at
+            least do a <command>mysqladmin flush-tables</command> before
+            you run <command>myisamchk</command>. Your tables
+            <emphasis>may become corrupted</emphasis> if the server and
+            <command>myisamchk</command> access the tables
+            simultaneously.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        With external locking in effect, each process that requires
+        access to a table acquires a file system lock for the table
+        files before proceeding to access the table. If all necessary
+        locks cannot be acquired, the process is blocked from accessing
+        the table until the locks can be obtained (after the process
+        that currently holds the locks releases them).
+      </para>
+
+      <para>
+        External locking affects server performance because the server
+        must sometimes wait for other processes before it can access
+        tables.
+      </para>
+
+      <para>
+        External locking is unnecessary if you run a single server to
+        access a given data directory (which is the usual case) and if
+        no other programs such as <command>myisamchk</command> need to
+        modify tables while the server is running. If you only
+        <emphasis>read</emphasis> tables with other programs, external
+        locking is not required, although <command>myisamchk</command>
+        might report warnings if the server changes tables while
+        <command>myisamchk</command> is reading them.
+      </para>
+
+      <para>
+        With external locking disabled, to use
+        <command>myisamchk</command>, you must either stop the server
+        while <command>myisamchk</command> executes or else lock and
+        flush the tables before running <command>myisamchk</command>.
+        (See <xref linkend="system-optimization"/>.) To avoid this
+        requirement, use the <literal role="stmt">CHECK TABLE</literal>
+        and <literal role="stmt">REPAIR TABLE</literal> statements to
+        check and repair <literal>MyISAM</literal> tables.
+      </para>
+
+      <para>
+        For <command>mysqld</command>, external locking is controlled by
+        the value of the
+        <literal role="sysvar">skip_external_locking</literal> system
+        variable. When this variable is enabled, external locking is
+        disabled, and vice versa. From MySQL 4.0 on, external locking is
+        disabled by default. Before MySQL 4.0, external locking is
+        enabled by default on Linux or when MySQL is configured to use
+        MIT-pthreads.
+      </para>
+
+      <para>
+        Use of external locking can be controlled at server startup by
+        using the <option role="mysqld">--external-locking</option> or
+        <option role="mysqld">--skip-external-locking</option> option.
+      </para>
+
+      <para>
+        If you do use external locking option to enable updates to
+        <literal>MyISAM</literal> tables from many MySQL processes, you
+        must ensure that the following conditions are satisfied:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            You should not use the query cache for queries that use
+            tables that are updated by another process.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            You should not start the server with the
+            <option role="mysqld">--delay-key-write=ALL</option> option
+            or use the <literal>DELAY_KEY_WRITE=1</literal> table option
+            for any shared tables. Otherwise, index corruption can
+            occur.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+      <para>
+        The easiest way to satisfy these conditions is to always use
+        <option role="mysqld">--external-locking</option> together with
+        <option role="mysqld">--delay-key-write=OFF</option> and
+        <option role="sysvar">--query-cache-size=0</option>. (This is
+        not done by default because in many setups it is useful to have
+        a mixture of the preceding options.)
+      </para>
+
+    </section>
+
+  </section>
+
+  <section id="optimizing-database-structure">
+
+    <title>Optimizing Database Structure</title>
+
+    <section id="data-size">
+
+      <title>Make Your Data as Small as Possible</title>
+
+      <indexterm>
+        <primary>data</primary>
+        <secondary>size</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>reducing</primary>
+        <secondary>data size</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>storage space</primary>
+        <secondary>minimizing</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>tables</primary>
+        <secondary>improving performance</secondary>
+      </indexterm>
+
+      <indexterm>
+        <primary>performance</primary>
+        <secondary>improving</secondary>
+      </indexterm>
+
+      <para>
+        One of the most basic optimizations is to design your tables to
+        take as little space on the disk as possible. This can result in
+        huge improvements because disk reads are faster, and smaller
+        tables normally require less main memory while their contents
+        are being actively processed during query execution. Indexing
+        also is a lesser resource burden if done on smaller columns.
+      </para>
+
+      <para>
+        MySQL supports many different storage engines (table types) and
+        row formats. For each table, you can decide which storage and
+        indexing method to use. Choosing the proper table format for
+        your application may give you a big performance gain. See
+        <xref linkend="storage-engines"/>.
+      </para>
+
+      <para>
+        You can get better performance for a table and minimize storage
+        space by using the techniques listed here:
+      </para>
+
+      <itemizedlist>
+
+        <listitem>
+          <para>
+            Use the most efficient (smallest) data types possible. MySQL
+            has many specialized types that save disk space and memory.
+            For example, use the smaller integer types if possible to
+            get smaller tables. <literal role="type">MEDIUMINT</literal>
+            is often a better choice than
+            <literal role="type">INT</literal> because a
+            <literal role="type">MEDIUMINT</literal> column uses 25%
+            less space.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Declare columns to be <literal>NOT NULL</literal> if
+            possible. It makes everything faster and you save one bit
+            per column. If you really need <literal>NULL</literal> in
+            your application, you should definitely use it. Just avoid
+            having it on all columns by default.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            For <literal>MyISAM</literal> tables, if you do not have any
+            variable-length columns
+            (<literal role="type">VARCHAR</literal>,
+            <literal role="type">TEXT</literal>, or
+            <literal role="type">BLOB</literal> columns), a fixed-size
+            row format is used. This is faster but unfortunately may
+            waste some space. See
+            <xref linkend="myisam-table-formats"/>. You can hint that
+            you want to have fixed length rows even if you have
+            <literal role="type">VARCHAR</literal> columns with the
+            <literal role="stmt">CREATE TABLE</literal> option
+            <literal>ROW_FORMAT=FIXED</literal>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            <literal>InnoDB</literal> tables use a compact storage
+            format. In versions of MySQL earlier than 5.0.3,
+            <literal>InnoDB</literal> rows contain some redundant
+            information, such as the number of columns and the length of
+            each column, even for fixed-size columns. By default, tables
+            are created in the compact format
+            (<literal>ROW_FORMAT=COMPACT</literal>). If you wish to
+            downgrade to older versions of MySQL, you can request the
+            old format with <literal>ROW_FORMAT=REDUNDANT</literal>.
+          </para>
+
+          <para>
+            The presence of the compact row format decreases row storage
+            space by about 20% at the cost of increasing CPU use for
+            some operations. If your workload is a typical one that is
+            limited by cache hit rates and disk speed it is likely to be
+            faster. If it is a rare case that is limited by CPU speed,
+            it might be slower.
+          </para>
+
+          <para>
+            The compact <literal>InnoDB</literal> format also changes
+            how <literal role="type">CHAR</literal> columns containing
+            UTF-8 data are stored. With
+            <literal>ROW_FORMAT=REDUNDANT</literal>, a UTF-8
+            <literal>CHAR(<replaceable>N</replaceable>)</literal>
+            occupies 3 &times; <replaceable>N</replaceable> bytes, given
+            that the maximum length of a UTF-8 encoded character is
+            three bytes. Many languages can be written primarily using
+            single-byte UTF-8 characters, so a fixed storage length
+            often wastes space. With
+            <literal>ROW_FORMAT=COMPACT</literal> format,
+            <literal>InnoDB</literal> allocates a variable amount of
+            storage in the range from <replaceable>N</replaceable> to 3
+            &times; <replaceable>N</replaceable> bytes for these columns
+            by stripping trailing spaces if necessary. The minimum
+            storage length is kept as <replaceable>N</replaceable> bytes
+            to facilitate in-place updates in typical cases.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            The primary index of a table should be as short as possible.
+            This makes identification of each row easy and efficient.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            Create only the indexes that you really need. Indexes are
+            good for retrieval but bad when you need to store data
+            quickly. If you access a table mostly by searching on a
+            combination of columns, create an index on them. The first
+            part of the index should be the column most used. If you
+            <emphasis>always</emphasis> use many columns when selecting
+            from the table, the first column in the index should be the
+            one with the most duplicates to obtain better compression of
+            the index.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            If it is very likely that a string column has a unique
+            prefix on the first number of characters, it is better to
+            index only this prefix, using MySQL's support for creating
+            an index on the leftmost part of the column (see
+            <xref linkend="create-index"/>). Shorter indexes are faster,
+            not only because they require less disk space, but because
+            they also give you more hits in the index cache, and thus
+            fewer disk seeks. See <xref linkend="server-parameters"/>.
+          </para>
+        </listitem>
+
+        <listitem>
+          <para>
+            In some circumstances, it can be beneficial to split into
+            two a table that is scanned very often. This is especially
+            true if it is a dynamic-format table and it is possible to
+            use a smaller static format table that can be used to find
+            the relevant rows when scanning the table.
+          </para>
+        </listitem>
+
+      </itemizedlist>
+
+    </section>
+
     <section id="table-cache">
 
       <title>How MySQL Opens and Closes Tables</title>


Modified: trunk/refman-6.0/sql-syntax-data-definition.xml
===================================================================
--- trunk/refman-6.0/sql-syntax-data-definition.xml	2010-07-14 15:11:37 UTC (rev 21727)
+++ trunk/refman-6.0/sql-syntax-data-definition.xml	2010-07-14 15:35:58 UTC (rev 21728)
Changed blocks: 1, Lines Added: 1, Lines Deleted: 1; 663 bytes

@@ -4876,7 +4876,7 @@
           <literal role="type">VARBINARY</literal>, and
           <literal role="type">BLOB</literal> columns. Indexing only a
           prefix of column values like this can make the index file much
-          smaller. See <xref linkend="indexes"/>.
+          smaller. See <xref linkend="column-indexes"/>.
         </para>
 
         <indexterm>


Thread
svn commit - mysqldoc@docsrva: r21728 - in trunk: . refman-4.1 refman-5.0 refman-5.1 refman-5.5 refman-6.0paul.dubois14 Jul