MySQL 5.6 Reference Manual-14.6 InnoDB Table Management

14.6 InnoDB Table Management mysql

 

14.6.1 Creating InnoDB Tablesios

14.6.2 Moving or Copying InnoDB Tables to Another Machinegit

14.6.3 Grouping DML Operations with Transactions算法

14.6.4 Converting Tables from MyISAM to InnoDBsql

14.6.5 AUTO_INCREMENT Handling in InnoDBshell

14.6.6 InnoDB and FOREIGN KEY Constraints數據庫

14.6.7 Limits on InnoDB Tables緩存

 

14.6.1 Creating InnoDB Tables 安全

 

To create an InnoDB table, use the CREATE TABLE statement. You do not need to specify the ENGINE=InnoDB clause if InnoDB is defined as the default storage engine, which is the default as of MySQL 5.5. You might still use ENGINE=InnoDB clause if you plan to use mysqldump or replication to replay the CREATE TABLE statement on a server where the default storage engine is not InnoDB.服務器

可使用CREATE TABLE語句建立一個InnoDB表。從MySQL5.5開始,InnoDB就是默認的存儲引擎,因此你不須要指定ENGINE=InnoDB子句。當你準備在默認引擎不是InnoDB的實例上使用mysqldump或者複製重現CREATE TABLE的時候仍然可使用ENGINE=InnoDB。

 

-- Default storage engine = InnoDB.

CREATE TABLE t1 (a INT, b CHAR (20), PRIMARY KEY (a));

-- Backward-compatible with older MySQL.

CREATE TABLE t2 (a INT, b CHAR (20), PRIMARY KEY (a)) ENGINE=InnoDB;

 

An InnoDB table and its indexes can be created in the system tablespace or in a file-per-table tablespace. When innodb_file_per_table is enabled, which is the default setting as of MySQL 5.6.6, an InnoDB table is implicitly created in an individual file-per-table tablespace. Conversely, when innodb_file_per_table is disabled, an InnoDB table is implicitly created in the system tablespace.

InnoDB的表和索引能夠建立在系統表空間或者file-per-table表空間裏。當開啓了自MySQL5.6.6開始默認的innodb_file_per_table,InnoDB表會隱式地建立在一個獨立的file-per-table表空間裏。相反,當innodb_file_per_table關閉的時候,InnoDB表會隱式地建立在系統表空間裏。

 

When you create an InnoDB table, MySQL creates a .frm file in a database directory under the MySQL data directory. For a table created in a file-per-table tablespace, an .ibd file is also created. A table created in the system tablespace is created in the existing system tablespace ibdata files.

當你建立了一個InnoDB表的時候,MySQL會在MySQL的數據目錄的數據庫目錄裏建立一個.frm,以及一個.ibd文件。建立在系統表空間裏的表會被放在現有的系統表空間ibdata文件裏。

 

Internally, InnoDB adds an entry for each table to the InnoDB data dictionary. The entry includes the database name. For example, if table t1 is created in the test database, the data dictionary entry is 'test/t1'. This means you can create a table of the same name (t1) in a different database, and the table names do not collide inside InnoDB.

在內部,InnoDB會爲每一個表在InnoDB的數據字典裏面建立一個包含數據庫名的條目。例如,表t1建立在test數據庫裏,數據字典條目就是'test/t1'。這也就意味着你能夠在不一樣的數據庫裏面建立名字相同的表。在InnoDB內部這些表的名字並不會衝突。

 

Viewing the Properties of InnoDB Tables

 

To view the properties of InnoDB tables, issue a SHOW TABLE STATUS statement:

執行SHOW TABLE STATUS語句查看InnoDB表的屬性:

 

mysql> SHOW TABLE STATUS FROM test LIKE 't%' \G;

*************************** 1. row ***************************

Name: t1

Engine: InnoDB

Version: 10

Row_format: Compact

Rows: 0

Avg_row_length: 0

Data_length: 16384

Max_data_length: 0

Index_length: 0

Data_free: 0

Auto_increment: NULL

Create_time: 2015-03-16 16:26:52

Update_time: NULL

Check_time: NULL

Collation: latin1_swedish_ci

Checksum: NULL

Create_options:

Comment:

1 row in set (0.00 sec)

 

In the status output, you see the Row format property of table t1 is Compact. Although that setting is fine for basic experimentation, consider using the Dynamic or Compressed row format to take advantage of InnoDB features such as table compression and off-page storage for long column values. Using these row formats requires that innodb_file_per_table is enabled (the default as of MySQL 5.6.6) and that innodb_file_format is set to Barracuda:

在狀態輸出裏面,你能夠看到t1表的Row format屬性是Compact。雖然根據基本的實驗這是一個不錯的設定,可是也能夠考慮使用InnoDB的特性優點使用Dynamic或者Compressed行格式,例如爲很長的列值使用表壓縮和不一樣的頁大小存儲(off-page storage)。

 

SET GLOBAL innodb_file_per_table=1;

SET GLOBAL innodb_file_format=barracuda;

CREATE TABLE t3 (a INT, b CHAR (20), PRIMARY KEY (a)) ROW_FORMAT=DYNAMIC;

CREATE TABLE t4 (a INT, b CHAR (20), PRIMARY KEY (a)) ROW_FORMAT=COMPRESSED;

 

InnoDB table properties may also be queried using the InnoDB Information Schema system tables:

InnoDB表的熟悉一樣也經過查詢InnoDB Information Schema的系統表:

 

SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME='test/t1' \G

*************************** 1. row ***************************

TABLE_ID: 42

NAME: test/t1

FLAG: 1

N_COLS: 5

SPACE: 24

FILE_FORMAT: Antelope

ROW_FORMAT: Compact

ZIP_PAGE_SIZE: 0

1 row in set (0.02 sec)

 

Defining a Primary Key for InnoDB Tables

 

Always set up a primary key for each InnoDB table, specifying the column or columns that:

爲每一個InnoDB表在這些列上創建主鍵:

 

  • Are referenced by the most important queries.
  • 最要查詢所引用的。

 

  • Are never left blank.
  • 不會爲空。

 

  • Never have duplicate values.
  • 沒有重複值。

 

  • Rarely if ever change value once inserted.
  • 一旦插入後不多修改。

 

For example, in a table containing information about people, you would not create a primary key on (firstname, lastname) because more than one person can have the same name, some people have blank last names, and sometimes people change their names. With so many constraints, often there is not an obvious set of columns to use as a primary key, so you create a new column with a numeric ID to serve as all or part of the primary key. You can declare an auto-increment column so that ascending values are filled in automatically as rows are inserted:

例如,在一個關於人口信息的表裏,你不能在(firstname, lastname)上建立主鍵由於有可能會有同名的狀況,有些只有last name,還有些人會修改他們的名字。正由於有這麼多的約束,這裏沒有明顯的列來做爲主鍵,那你能夠建立一個新的數字ID列來做爲主鍵。你能夠把列定義成自增加列,使得在insert的時候自動填充遞增的值:

 

-- The value of ID can act like a pointer between related items in different tables.

CREATE TABLE t5 (id INT AUTO_INCREMENT, b CHAR (20), PRIMARY KEY (id));

-- The primary key can consist of more than one column. Any autoinc column must come first.

CREATE TABLE t6 (id INT AUTO_INCREMENT, a INT, b CHAR (20), PRIMARY KEY (id,a));

 

Although the table works correctly without defining a primary key, the primary key is involved with many aspects of performance and is a crucial design aspect for any large or frequently used table. It is recommended that you always specify a primary key in the CREATE TABLE statement. If you create the table, load data, and then run ALTER TABLE to add a primary key later, that operation is much slower than defining the primary key when creating the table.

雖然即便沒有定義主鍵表也能工做,可是主鍵涉及了不少性能方面的問題,以及對大表或者頻繁使用的表的核心設計問題,因此建議你在CREATE TABLE的時候仍是要指定一個主鍵。若是你建立了表,加載了數據,而後再運行ALTER TABLE來加主鍵,那這個操做將會比在建表的時候定義主鍵要慢得不少。

 

14.6.2 Moving or Copying InnoDB Tables to Another Machine

 

This section describes techniques for moving or copying some or all InnoDB tables to a different server. For example, you might move an entire MySQL instance to a larger, faster server; you might clone an entire MySQL instance to a new replication slave server; you might copy individual tables to another server to develop and test an application, or to a data warehouse server to produce reports.

這一章節講述瞭如何複製或者移動InnoDB表到不一樣的實例裏。例如,你要把整個MySQL實例移動到一個更大,速度更快的服務器上;你要克隆整個MySQL實例到一個新的主從架構的從機上;你能夠也能夠複製個別表到開發或者測試環境裏,又或者是數據倉庫裏。

 

Techniques for moving or copying InnoDB tables include:

這些移動複製InnoDB表的方法有:

 

 

 

 

 

Using Lowercase Names for Cross-Platform Moving or Copying

 

On Windows, InnoDB always stores database and table names internally in lowercase. To move databases in a binary format from Unix to Windows or from Windows to Unix, create all databases and tables using lowercase names. A convenient way to accomplish this is to add the following line to the [mysqld] section of your my.cnf or my.ini file before creating any databases or tables:

在Windows上,InnoDB在內部用小寫來存儲數據庫和表的名字。要把二進制格式的數據庫從Unix移動到Windows上或者從Windows到Unix上,數據庫和表的名字最好都用小寫。還有一種方法能夠實現這樣的目的就是在建立任何的數據庫或表以前,在配置文件my.cnf or my.ini的[mysqld]里加入下面的內容:

 

[mysqld]

lower_case_table_names=1

 

Transportable Tablespaces

 

Introduced in MySQL 5.6.6, the transportable tablespaces feature uses FLUSH TABLES ... FOR EXPORT to ready InnoDB tables for copying from one server instance to another. To use this feature, InnoDB tables must be created with innodb_file_per_table set to ON so that each InnoDB table has its own tablespace. For usage information, see Section 14.5.6, "Copying File-Per-Table Tablespaces to Another Server".

在MySQL5.6.6裏,可使用FLUSH TABLES ... FOR EXPORT的傳輸表空間特性來把一個InnoDB表複製到另外一個實例上。要使用這個特性,innodb_file_per_table必須是要打開的,讓每一個InnoDB表都有本身的表空間。相關的使用信息能夠查看Section 14.5.6, "Copying File-Per-Table Tablespaces to Another Server"。

 

MySQL Enterprise Backup

 

The MySQL Enterprise Backup product lets you back up a running MySQL database, including InnoDB and MyISAM tables, with minimal disruption to operations while producing a consistent snapshot of the database. When MySQL Enterprise Backup is copying InnoDB tables, reads and writes to both InnoDB and MyISAM tables can continue. During the copying of MyISAM and other non-InnoDB tables, reads (but not writes) to those tables are permitted. In addition, MySQL Enterprise Backup can create compressed backup files, and back up subsets of InnoDB tables. In conjunction with the MySQL binary log, you can perform point-in-time recovery. MySQL Enterprise Backup is included as part of the MySQL Enterprise subscription.

MySQL Enterprise Backup可讓你備份一個正在運行的MySQL數據庫,包括InnoDB和MyISAM表,並且在生產數據庫一致性快照的時候可以最小化地中斷正常的操做。當MySQL Enterprise Backup複製InnoDB表的時候,InnoDB和MyISAM表都可以繼續讀和寫的操做。在複製MyISAM和其餘非InnoDB表的時候,讀操做(不包括寫)是被容許的。另外,MySQL Enterprise Backup可以建立壓縮過的備份文件,並以此來備份InnoDB表的子集。連同MySQL的binary log,你還能夠執行基於時間點的恢復。MySQL Enterprise Backup包含在MySQL Enterprise裏面的。

 

For more details about MySQL Enterprise, see Section 25.2, "MySQL Enterprise Backup Overview".

更多關於MySQL Enterprise的細節能夠查看Section 25.2, "MySQL Enterprise Backup Overview"。

 

Copying Data Files (Cold Backup Method)

 

You can move an InnoDB database simply by copying all the relevant files listed under "Cold Backups" in Section 14.16, "InnoDB Backup and Recovery".

如Section 14.16, "InnoDB Backup and Recovery"裏面"Cold Backups"所講述的,你能夠複製全部相關的文件來簡單地移動InnoDB數據庫。

 

Like MyISAM data files, InnoDB data and log files are binary-compatible on all platforms having the same floating-point number format. If the floating-point formats differ but you have not used FLOAT or DOUBLE data types in your tables, then the procedure is the same: simply copy the relevant files.

相似於MyISAM的數據文件,InnoDB的數據和日誌文件在全部使用相同浮點格式的平臺上都是兼容的。若是浮點格式不一樣可是在表裏也沒有使用FLOAT or DOUBLE的數據類型,也是能夠進行簡單複製的。

 

Portability Considerations for .ibd Files

 

When you move or copy .ibd files, the database directory name must be the same on the source and destination systems. The table definition stored in the InnoDB shared tablespace includes the database name. The transaction IDs and log sequence numbers stored in the tablespace files also differ between databases.

當你移動或者複製.ibd文件的時候,源端和目標端的數據庫名必須是相同的。表定義存儲的InnoDB共享表空間裏也包括了數據庫名。不一樣數據庫之間transaction IDs and log sequence numbers也是不一樣的。

 

To move an .ibd file and the associated table from one database to another, use a RENAME TABLE statement:

要把一個.ibd文件和相關的表從一個數據庫移動到另外一個的時候,可使用RENAME TABLE語句:

 

RENAME TABLE db1.tbl_name TO db2.tbl_name;

 

If you have a "clean" backup of an .ibd file, you can restore it to the MySQL installation from which it originated as follows:

若是你有一個"乾淨的".ibd文件備份,你能夠在下面的MySQL原始安裝步驟裏恢復它:

 

1.The table must not have been dropped or truncated since you copied the .ibd file, because doing so changes the table ID stored inside the tablespace.

1.自從你複製了.ibd文件以後表必須是沒有drop或者truncate的,由於這些操做會修改存儲在表空間裏的 table ID

 

2.Issue this ALTER TABLE statement to delete the current .ibd file:

2.執行ALTER TABLE語句來刪除當前的.ibd文件:

 

ALTER TABLE tbl_name DISCARD TABLESPACE;

 

3.Copy the backup .ibd file to the proper database directory.

3.複製備份的.ibd文件到適當的數據庫目錄。

 

4.Issue this ALTER TABLE statement to tell InnoDB to use the new .ibd file for the table:

4.執行ALTER TABLE語句告訴InnoDB爲表使用新的.ibd文件:

 

ALTER TABLE tbl_name IMPORT TABLESPACE;

 

Note

 

The ALTER TABLE ... IMPORT TABLESPACE feature does not enforce foreign key constraints on imported data.

ALTER TABLE ... IMPORT TABLESPACE特性不會在導入的數據上強制實施外鍵約束。

 

In this context, a "clean" .ibd file backup is one for which the following requirements are satisfied:

在這個環境裏,"乾淨的".ibd文件備份是要知足下面的要求的:

 

  • There are no uncommitted modifications by transactions in the .ibd file.
  • .ibd文件裏沒有事務未提交的修改。

 

  • There are no unmerged insert buffer entries in the .ibd file.
  • .ibd文件裏沒有未合併的insert buffer條目。

 

  • Purge has removed all delete-marked index records from the .ibd file.
  • purge操做會從.ibd文件裏面移除全部有刪除標記的索引記錄。

 

  • mysqld has flushed all modified pages of the .ibd file from the buffer pool to the file.
  • mysqld已經從buffer pool裏面把.ibd文件相關的修改過的數據頁刷新到了文件上。

 

You can make a clean backup .ibd file using the following method:

你可使用下面的方法建立一個乾淨的.ibd備份文件:

 

1.Stop all activity from the mysqld server and commit all transactions.

1.在mysqld服務上中止全部的活動,並提交全部的事務。

 

2.Wait until SHOW ENGINE INNODB STATUS shows that there are no active transactions in the database, and the main thread status of InnoDB is Waiting for server activity. Then you can make a copy of the .ibd file.

2.等到SHOW ENGINE INNODB STATUS顯示的數據庫裏已經沒有活動的事務的,InnoDB的主線程狀態是Waiting for server activity。這個時候就能夠複製.ibd文件了。

 

Another method for making a clean copy of an .ibd file is to use the MySQL Enterprise Backup product:

另外一個建立乾淨的.ibd文件的方法是使用MySQL Enterprise Backup:

 

1.Use MySQL Enterprise Backup to back up the InnoDB installation.

1.使用MySQL Enterprise Backup來備份InnoDB安裝。

 

2.Start a second mysqld server on the backup and let it clean up the .ibd files in the backup.

2.在備份上啓動第二個mysqld服務,並在備份裏面清除.ibd文件。

 

Export and Import (mysqldump)

 

You can use mysqldump to dump your tables on one machine and then import the dump files on the other machine. Using this method, it does not matter whether the formats differ or if your tables contain floating-point data.

你可使用mysqldump從一臺機器上導出表,再在另外一臺機器上導入這些dump文件。這種方法能夠忽略平臺的差別。

 

One way to increase the performance of this method is to switch off autocommit mode when importing data, assuming that the tablespace has enough space for the big rollback segment that the import transactions generate. Do the commit only after importing a whole table or a segment of a table.

這種方式下想要增長性能能夠在導入的時候關閉autocommit,可是要確保表空間有足夠的回滾空間來存放導入的事務。而後在導入完整個表或者表的分段的時候再執行commit。

 

14.6.3 Grouping DML Operations with Transactions

 

By default, connection to the MySQL server begins with autocommit mode enabled, which automatically commits every SQL statement as you execute it. This mode of operation might be unfamiliar if you have experience with other database systems, where it is standard practice to issue a sequence of DML statements and commit them or roll them back all together.

默認狀況下,鏈接到MySQL服務開始的時候使用的是autocommit模式,這會在你執行的每一個SQL語句後面自動進行commit。這種操做模式可能不一樣於其餘的數據庫系統,其餘數據庫的標準慣例是執行完DML語句以後在進行commit或者rollback。

 

To use multiple-statement transactions, switch autocommit off with the SQL statement SET autocommit = 0 and end each transaction with COMMIT or ROLLBACK as appropriate. To leave autocommit on, begin each transaction with START TRANSACTION and end it with COMMIT or ROLLBACK. The following example shows two transactions. The first is committed; the second is rolled back.

要使用多語句事務,則要使用SET autocommit = 0來關閉autocommit,並在每一個事務的尾端執行適當的COMMIT或者ROLLBACK。還有一種方式能夠關閉autocommit,在每一個事務開始的時候運行START TRANSACTION,在結尾的地方運行COMMIT或者ROLLBACK。下面的例子顯示了兩個事務,第一個進行了commit,第二個作了rollback。

 

shell> mysql test

 

mysql> CREATE TABLE customer (a INT, b CHAR (20), INDEX (a));

Query OK, 0 rows affected (0.00 sec)

mysql> -- Do a transaction with autocommit turned on.

mysql> START TRANSACTION;

Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO customer VALUES (10, 'Heikki');

Query OK, 1 row affected (0.00 sec)

mysql> COMMIT;

Query OK, 0 rows affected (0.00 sec)

mysql> -- Do another transaction with autocommit turned off.

mysql> SET autocommit=0;

Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO customer VALUES (15, 'John');

Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO customer VALUES (20, 'Paul');

Query OK, 1 row affected (0.00 sec)

mysql> DELETE FROM customer WHERE b = 'Heikki';

Query OK, 1 row affected (0.00 sec)

mysql> -- Now we undo those last 2 inserts and the delete.

mysql> ROLLBACK;

Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM customer;

+------+--------+

| a | b |

+------+--------+

| 10 | Heikki |

+------+--------+

1 row in set (0.00 sec)

mysql>

 

Transactions in Client-Side Languages

 

In APIs such as PHP, Perl DBI, JDBC, ODBC, or the standard C call interface of MySQL, you can send transaction control statements such as COMMIT to the MySQL server as strings just like any other SQL statements such as SELECT or INSERT. Some APIs also offer separate special transaction commit and rollback functions or methods.

在一些其餘程序的接口如PHP, Perl DBI, JDBC, ODBC, or the standard C上,你能夠和其餘的SQL語句同樣經過發送COMMIT到MySQL服務器來控制事務。一些接口還提供獨立的特殊事務的commit和rollback函數。

 

14.6.4 Converting Tables from MyISAM to InnoDB

 

If you have existing tables, and applications that use them, that you want to convert to InnoDB for better reliability and scalability, use the following guidelines and tips. This section assumes most such tables were originally MyISAM, which was formerly the default.

若是你已經有一些表,應用程序也都在使用它們,你想把它們轉化成InnoDB以得到更好的可靠性和可擴展性,就可使用下面的知道建議。這一章節假設有不少原來默認的就是MyISAM的表。

 

Reduce Memory Usage for MyISAM, Increase Memory Usage for InnoDB

 

As you transition away from MyISAM tables, lower the value of the key_buffer_size configuration option to free memory no longer needed for caching results. Increase the value of the innodb_buffer_pool_size configuration option, which performs a similar role of allocating cache memory for InnoDB tables. The InnoDB buffer pool caches both table data and index data, so it does double duty in speeding up lookups for queries and keeping query results in memory for reuse.

由於MyISAM表是不能使用事務的,那麼能夠把key_buffer_size配置成一個較小的值來節約更多的內存。增長innodb_buffer_pool_size配置參數的值,讓InnoDB能夠分配更多的內存。InnoDB buffer pool能夠同時緩存表數據和索引數據,因此它有雙重的責任來加速查詢的速度,並把查詢結果緩存在內存裏進行重複使用。

 

  • Allocate as much memory to this option as you can afford, often up to 80% of physical memory on the server.
  • 儘量多地分配更多的內存,一般會佔到整個服務器物理內存的80%。

 

  • If the operating system runs short of memory for other processes and begins to swap, reduce the innodb_buffer_pool_size value. Swapping is such an expensive operation that it drastically reduces the benefit of the cache memory.
  • 若是操做系統運行了其餘程序值剩餘很小的內存,而且已經開始使用swap了,那就要減小innodb_buffer_pool_size的值。swapping是一個很昂貴的操做,它會大幅減小內存緩存所帶來的好處。

 

  • If the innodb_buffer_pool_size value is several gigabytes or higher, consider increasing the values of innodb_buffer_pool_instances. Doing so helps on busy servers where many connections are reading data into the cache at the same time.
  • 若是innodb_buffer_pool_size的值有好幾個G或者更高,那就要考慮增長innodb_buffer_pool_instances的值。在繁忙的服務器上這樣作可以在同一個時間點上讓多個鏈接同時從緩存裏都數據。

 

  • On a busy server, run benchmarks with the Query Cache turned off. The InnoDB buffer pool provides similar benefits, so the Query Cache might be tying up memory unnecessarily.
  • 在繁忙的服務器上,關閉Query Cache來作基準測試。InnoDB buffer pool提供了相似的功能,因此Query Cache可能就不是必須的了。

 

Watch Out for Too-Long Or Too-Short Transactions

 

Because MyISAM tables do not support transactions, you might not have paid much attention to the autocommit configuration option and the COMMIT and ROLLBACK statements. These keywords are important to allow multiple sessions to read and write InnoDB tables concurrently, providing substantial scalability benefits in write-heavy workloads.

由於MyISAM表不支持事務,你可能不怎麼會關注autocommit的配置以及COMMIT,ROLLBACK語句。但這些關鍵字對於多session併發讀寫InnoDB表則是很是重要的,它們可以在寫負載高的狀況下提供更好的擴展性。

 

While a transaction is open, the system keeps a snapshot of the data as seen at the beginning of the transaction, which can cause substantial overhead if the system inserts, updates, and deletes millions of rows while a stray transaction keeps running. Thus, take care to avoid transactions that run for too long:

當開啓了一個事務,系統會保持一個事務開啓點時數據的快照,那麼若是事務繼續在運行,那麼系統就要大量地Insert,update和delete成千上萬的行數據,並帶來大量的系統資源損耗。所以,要避免事務太長:

 

  • If you are using a mysql session for interactive experiments, always COMMIT (to finalize the changes) or ROLLBACK (to undo the changes) when finished. Close down interactive sessions rather than leaving them open for long periods, to avoid keeping transactions open for long periods by accident.
  • 若是你使用一個mysql session來作交互式實驗,而且在結束的時候是須要手動COMMIT或者ROLLBACK的。這種狀況相對於長時間開着事務,更好的辦法是及時關閉交互式的session,這樣可以避免長事務帶來的意外。

 

  • Make sure that any error handlers in your application also ROLLBACK incomplete changes or COMMIT completed changes.
  • 確保應用程序有error handler,這樣可以ROLLBACK不完整修改,或者進行COMMIT。

 

  • ROLLBACK is a relatively expensive operation, because INSERT, UPDATE, and DELETE operations are written to InnoDB tables prior to the COMMIT, with the expectation that most changes will be committed successfully and rollbacks will be rare. When experimenting with large volumes of data, avoid making changes to large numbers of rows and then rolling back those changes.
  • ROLLBACK是一個至關昂貴的操做,由於對於寫入到InnoDB表的DML操做優先是進行COMMIT的,咱們所指望的大部分的修改是成功提交的,而要回滾的畢竟是少部分。當進行大批量數據嘗試的時候,要避免修改大量的行數據並再對其進行回滾。

 

  • When loading large volumes of data with a sequence of INSERT statements, periodically COMMIT the results to avoid having transactions that last for hours. In typical load operations for data warehousing, if something goes wrong, you TRUNCATE TABLE and start over from the beginning rather than doing a ROLLBACK.
  • 當要順序執行INSERT語句來加載大量數據的時候,要按期執行COMMIT來避免事務持續得時間太長。在一般的數據倉庫進行加載操做的時候,若是發生了錯誤,相對而言應該是TRUNCATE TABLE而後從新開始,而不是執行ROLLBACK操做。

 

The preceding tips save memory and disk space that can be wasted during too-long transactions. When transactions are shorter than they should be, the problem is excessive I/O. With each COMMIT, MySQL makes sure each change is safely recorded to disk, which involves some I/O.

太長的事務會浪費內存和磁盤的空間。可是當事務過短的時候,過多的I/O也那會是個問題。每一個COMMIT語句,MySQL都要確保每一個修改都已經安全寫入到磁盤上,這就涉及到了不少的I/O操做。

 

  • For most operations on InnoDB tables, you should use the setting autocommit=0. From an efficiency perspective, this avoids unnecessary I/O when you issue large numbers of consecutive INSERT, UPDATE, or DELETE statements. From a safety perspective, this allows you to issue a ROLLBACK statement to recover lost or garbled data if you make a mistake on the mysql command line, or in an exception handler in your application.
  • 對於大多數在InnoDB表上的操做,你應該設定autocommit=0。從效率的角度來講,當你執行大量連續的DML操做時可以避免沒必要要的I/O。從安全性來講,若是你執行了一個錯誤的mysql命令或者在程序中進行了異常處理,那這也能容許你執行ROLLBACK來恢復丟失或者錯亂的數據。

 

  • The time when autocommit=1 is suitable for InnoDB tables is when running a sequence of queries for generating reports or analyzing statistics. In this situation, there is no I/O penalty related to COMMIT or ROLLBACK, and InnoDB can automatically optimize the read-only workload.
  • 當你爲生成報表或者分析統計而運行一系列查詢的時候,對於InnoDB表來講autocommit=1是更爲合適的。在這種狀況下,沒有關閉COMMIT或者ROLLBACK的I/O處罰,InnoDB也會自動優化只讀的環境。

 

  • If you make a series of related changes, finalize all those changes at once with a single COMMIT at the end. For example, if you insert related pieces of information into several tables, do a single COMMIT after making all the changes. Or if you run many consecutive INSERT statements, do a single COMMIT after all the data is loaded; if you are doing millions of INSERT statements, perhaps split up the huge transaction by issuing a COMMIT every ten thousand or hundred thousand records, so the transaction does not grow too large.
  • 若是你進行了一系列的修改,能夠在結尾經過一次COMMIT定形全部的修改。例如,你要插入相關的信息到不一樣的表上,能夠在全部修改完成以後執行一個單獨的COMMIT。又或者你要運行不少連續的INSERT語句,那能夠在全部的數據加載完以後統一進行COMMIT;若是你要執行上百萬的INSERT,那能夠把這個大事務進行分割,對每一萬個或者十萬個進行分批COMMIT,這樣事務就不會增加得過大。

 

  • Remember that even a SELECT statement opens a transaction, so after running some report or debugging queries in an interactive mysql session, either issue a COMMIT or close the mysql session.
  • 記住即便是隻在事務裏打開一個SELECT語句,在mysql交互式session裏運行完一些報表查詢以後,也要執行COMMIT或者是關閉mysql session。

 

Don't Worry Too Much About Deadlocks

 

You might see warning messages referring to "deadlocks" in the MySQL error log, or the output of SHOW ENGINE INNODB STATUS. Despite the scary-sounding name, a deadlock is not a serious issue for InnoDB tables, and often does not require any corrective action. When two transactions start modifying multiple tables, accessing the tables in a different order, they can reach a state where each transaction is waiting for the other and neither can proceed. MySQL immediately detects this condition and cancels (rolls back) the "smaller" transaction, allowing the other to proceed.

你可能會在MySQL的error log或者是SHOW ENGINE INNODB STATUS的輸出裏看到相關"deadlocks(死鎖)"的警告信息。除去不怎麼好的名字,死鎖對於InnoDB表來講並非什麼嚴重的問題,也不須要什麼補救的動做。當兩個事務以不一樣的順序訪問修改多個表的時候,那就會發生相互等待對方的狀況。MySQL會當即發現這種狀況,並取消(回滾)較小的那個事務,以便另外一個操做可以繼續。

 

Your applications do need error-handling logic to restart a transaction that is forcibly cancelled like this. When you re-issue the same SQL statements as before, the original timing issue no longer applies: either the other transaction has already finished and yours can proceed, or the other transaction is still in progress and your transaction waits until it finishes.

你的應用程序要有錯誤處理邏輯來重啓事務以便強制取消。當你再執行和以前相同的SQL語句的時候,原來事務的時間戳將再也不適用:要麼是其餘的事務已經結束而你的仍然在繼續,要麼是其餘的事務仍然在處理而你的事務則要等到其結束。

 

If deadlock warnings occur constantly, you might review the application code to reorder the SQL operations in a consistent way, or to shorten the transactions. You can test with the innodb_print_all_deadlocks option enabled to see all deadlock warnings in the MySQL error log, rather than only the last warning in the SHOW ENGINE INNODB STATUS output.

若是不斷地發生死鎖的警告,你須要review應用程序的代碼以一致的方式從新排序SQL的操做,又或者再減短事務。你能夠經過開啓innodb_print_all_deadlocks參數進行測試來查看MySQL的error log裏面全部的死鎖警告(SHOW ENGINE INNODB STATUS的輸出裏只有最後一次的警告)。

 

Plan the Storage Layout

 

To get the best performance from InnoDB tables, you can adjust a number of parameters related to storage layout.

InnoDB表要等到最佳的性能,你能夠調整一系列存儲佈局相關的參數。

 

When you convert MyISAM tables that are large, frequently accessed, and hold vital data, investigate and consider the innodb_file_per_table, innodb_file_format, and innodb_page_size configuration options, and the ROW_FORMAT and KEY_BLOCK_SIZE clauses of the CREATE TABLE statement.

當你要轉換的MyISAM表很是大,並且還要頻繁訪問,又是相當重要的時候,那就要調查考慮這幾個參數:innodb_file_per_table, innodb_file_format, and innodb_page_size,還有在CREATE TABLE語句中的ROW_FORMAT and KEY_BLOCK_SIZE子句。

 

During your initial experiments, the most important setting is innodb_file_per_table. When this setting is enabled, which is the default as of MySQL 5.6.6, new InnoDB tables are implicitly created in file-per-table tablespaces. In contrast with the InnoDB system tablespace, file-per-table tablespaces allow disk space to be reclaimed by the operating system when a table is truncated or dropped. File-per-table tablespaces also support the Barracuda file format and associated features such as table compression and off-page storage for long variable-length columns. For more information, see Section 14.5.4, "InnoDB File-Per-Table Tablespaces".

開始的實驗證實innodb_file_per_table是最爲重要的參數。當這個參數開啓(從MySQL5.6.6開始默認是開啓的)的時候,新的InnoDB表會隱式地建立在file-per-table表空間裏。相對於InnoDB的系統表空間,當表被truncate或者drop的時候file-per-table表空間容許磁盤空間能被操做系統進行回收利用。file-per-table表空間還支持Barracuda文件格式以及其相關的特性,例如表壓縮,以及off-page storage for long variable-length columns。更多信息能夠查看Section 14.5.4, "InnoDB File-Per-Table Tablespaces"。

 

Converting an Existing Table

 

To convert a non-InnoDB table to use InnoDB use ALTER TABLE:

使用ALTER TABLE把非InnoDB錶轉成InnoDB表:

 

ALTER TABLE table_name ENGINE=InnoDB;

 

Important

 

Do not convert MySQL system tables in the mysql database (such as user or host) to the InnoDB type. This is an unsupported operation. The system tables must always be of the MyISAM type.

不要把在mysql數據庫裏的MySQL系統錶轉化成InnoDB的類型。這個操做是不支持的。系統表必需要是MyISAM類型的。

 

Cloning the Structure of a Table

 

You might make an InnoDB table that is a clone of a MyISAM table, rather than doing the ALTER TABLE conversion, to test the old and new table side-by-side before switching.

你能夠把一個MyISAM表克隆成InnoDB表,而不用執行ALTER TABLE來進行轉換,這樣能夠在切換以前對新舊錶分別進行測試。

 

Create an empty InnoDB table with identical column and index definitions. Use show create table table_name\G to see the full CREATE TABLE statement to use. Change the ENGINE clause to ENGINE=INNODB.

建立一個空的有相同列和索引定義的InnoDB表。使用create table table_name\G能夠看到完整的CREATE TABLE語句來使用,只要把ENGINE子句改爲ENGINE=INNODB。

 

Transferring Existing Data

 

To transfer a large volume of data into an empty InnoDB table created as shown in the previous section, insert the rows with INSERT INTO innodb_table SELECT * FROM myisam_table ORDER BY primary_key_columns.

要把大量的數據傳輸到上文建立的空InnoDB表裏,能夠經過INSERT INTO innodb_table SELECT * FROM myisam_table ORDER BY primary_key_columns來插入數據。

 

You can also create the indexes for the InnoDB table after inserting the data. Historically, creating new secondary indexes was a slow operation for InnoDB, but now you can create the indexes after the data is loaded with relatively little overhead from the index creation step.

你還能夠在插入數據以後爲InnoDB表建立索引。之前,對於InnoDB來講建立一個新的secondary index是一個很是慢的操做,但如今在加載完數據以後建立索引只要不多的成本開銷。

 

If you have UNIQUE constraints on secondary keys, you can speed up a table import by turning off the uniqueness checks temporarily during the import operation:

若是你在secondary index上有UNIQUE約束,那你能夠在導入操做的時候臨時關閉惟一檢查來加快導入的速度:

 

SET unique_checks=0;

... import operation ...

SET unique_checks=1;

 

For big tables, this saves disk I/O because InnoDB can use its change buffer to write secondary index records as a batch. Be certain that the data contains no duplicate keys. unique_checks permits but does not require storage engines to ignore duplicate keys.

對於大表來講,這可以減小磁盤的I/O,由於InnoDB能夠用它本身的change buffer來批量寫secondary index記錄。固然你須要本身去確認導入的沒有重複的key,unique_checks會容許你插入重複key但不會要求存儲引擎去忽略重複的key。

 

To get better control over the insertion process, you might insert big tables in pieces:

爲了更好地控制插入操做,你能夠分片插入大表:

 

INSERT INTO newtable SELECT * FROM oldtable

WHERE yourkey > something AND yourkey <= somethingelse;

 

After all records have been inserted, you can rename the tables.

在全部的記錄都被插入以後,那你就能夠重命名錶了。

 

During the conversion of big tables, increase the size of the InnoDB buffer pool to reduce disk I/O, to a maximum of 80% of physical memory. You can also increase the sizes of the InnoDB log files.

在轉換大表的過程當中,適當增長InnoDB buffer pool的值可以減小磁盤的I/O,最大能夠增長到物理內存的80%。一樣你也能夠增長InnoDB日誌文件的大小。

 

Storage Requirements

 

If you intend to make several temporary copies of your data in InnoDB tables during the conversion process, it is recommended that you create the tables in file-per-table tablespaces so that you can reclaim the disk space when you drop the tables. As mentioned previously, when the innodb_file_per_table option is enabled, newly created InnoDB tables are implicitly created in file-per-table tablespaces.

若是你想要在轉換的過程當中多作幾個臨時拷貝,那就要求你把表建在file-per-table的表空間裏,這樣當你刪除表的時候就能再利用磁盤空間。就如前面是所說的,當開啓了innodb_file_per_table,最新建立的InnoDB表會隱式地建立在file-per-table表空間裏。

 

Whether you convert the MyISAM table directly or create a cloned InnoDB table, make sure that you have sufficient disk space to hold both the old and new tables during the process. InnoDB tables require more disk space than MyISAM tables. If an ALTER TABLE operation runs out of space, it starts a rollback, and that can take hours if it is disk-bound. For inserts, InnoDB uses the insert buffer to merge secondary index records to indexes in batches. That saves a lot of disk I/O. For rollback, no such mechanism is used, and the rollback can take 30 times longer than the insertion.

不管你是直接轉換MyISAM表仍是建立了一個克隆的InnoDB表,都要確保有足夠的磁盤空間在處理過程當中可以同時保存新舊錶的數據。相對於MyISAM表,InnoDB表會要求更多的磁盤空間。若是ALTER TABLE運行的時候磁盤空間不夠了,那麼實例就會進行回滾,那可能就會要花費數個小時。對於插入操做,InnoDB會使用insert buffer來批量合併secondary index記錄,這樣就能節省不少的磁盤I/O。For rollback, no such mechanism is used, and the rollback can take 30 times longer than the insertion.

 

In the case of a runaway rollback, if you do not have valuable data in your database, it may be advisable to kill the database process rather than wait for millions of disk I/O operations to complete. For the complete procedure, see Section 14.19.2, "Forcing InnoDB Recovery".

對於這種失控回滾的狀況,若是數據庫中的數據不是過重要,那麼比較明智的作法是kill掉數據庫的操做線程,而不是等待上百萬的磁盤I/O操做完成。整個完整的過程能夠查看Section 14.19.2, "Forcing InnoDB Recovery"。

 

Carefully Choose a PRIMARY KEY for Each Table

 

The PRIMARY KEY clause is a critical factor affecting the performance of MySQL queries and the space usage for tables and indexes. Perhaps you have phoned a financial institution where you are asked for an account number. If you do not have the number, you are asked for a dozen different pieces of information to "uniquely identify" yourself. The primary key is like that unique account number that lets you get straight down to business when querying or modifying the information in a table. Every row in the table must have a primary key value, and no two rows can have the same primary key value.

主鍵是影響MySQL查詢性能以及表和索引使用空間的關鍵要素。假設你打電話給金融機構要求一個賬號號碼。若是你沒有號碼,那你就須要一達不一樣的信息來"惟一標識"你本身。主鍵就像那個惟一的賬號號碼,當你查詢或者修改一個的表的信息的時候能夠當即找到。表裏的每一行記錄都要有一個主鍵值,並且不會有兩行記錄有相同主鍵值的狀況。

 

Here are some guidelines for the primary key, followed by more detailed explanations.

這裏是一些針對於主鍵的指導方針:

 

  • Declare a PRIMARY KEY for each table. Typically, it is the most important column that you refer to in WHERE clauses when looking up a single row.
  • 爲每一個表都定義一個主鍵。一般,是那種涉及WHERE語句中最重要的列,可讓你定位到單獨的一行記錄。

 

  • Declare the PRIMARY KEY clause in the original CREATE TABLE statement, rather than adding it later through an ALTER TABLE statement.
  • 在CREATE TABLE的時候就定義好主鍵,而不是以後經過ALTER TABLE語句來添加主鍵。

 

  • Choose the column and its data type carefully. Prefer numeric columns over character or string ones.
  • 當心選擇列和它的數據類型。相對於字符或者字符串,數值型的更爲合適。

 

  • Consider using an auto-increment column if there is not another stable, unique, non-null, numeric column to use.
  • 若是沒有適當的惟一,非空,數值型的列使用,那麼能夠考慮使用一個自增加的列。

 

  • An auto-increment column is also a good choice if there is any doubt whether the value of the primary key column could ever change. Changing the value of a primary key column is an expensive operation, possibly involving rearranging data within the table and within each secondary index.
  • 若是懷疑主鍵首選列的值有可能會變化的話,那麼自增加列也是一個不錯的。修改主鍵列的值是一個很是昂貴的操做,這其中涉及到重排表中的數據以及每個secondary index。

 

Consider adding a primary key to any table that does not already have one. Use the smallest practical numeric type based on the maximum projected size of the table. This can make each row slightly more compact, which can yield substantial space savings for large tables. The space savings are multiplied if the table has any secondary indexes, because the primary key value is repeated in each secondary index entry. In addition to reducing data size on disk, a small primary key also lets more data fit into the buffer pool, speeding up all kinds of operations and improving concurrency.

爲沒有主鍵的表考慮增長一個主鍵。在大表上可使用最小的實際數值類型的列來作主鍵。這樣可使得每一行更爲緊湊,在大表上能夠節約大量的空間。若是表有不少的secondary index,那這節約的空間都是成倍的,由於主鍵值是要重疊在每一個secondary index條目上的。另外這還能減小磁盤上的數據大小。小的主鍵可以讓buffer pool裝載更多的數據,這樣也就加快各類類型的操做,提高了併發性。

 

If the table already has a primary key on some longer column, such as a VARCHAR, consider adding a new unsigned AUTO_INCREMENT column and switching the primary key to that, even if that column is not referenced in queries. This design change can produce substantial space savings in the secondary indexes. You can designate the former primary key columns as UNIQUE NOT NULL to enforce the same constraints as the PRIMARY KEY clause, that is, to prevent duplicate or null values across all those columns.

若是表已經在一個比較長的列上有主鍵了,例如VARCHAR類型的列,那麼能夠考慮增長一個自增加的列併爲主鍵,即便這個在查詢中不會被引用。這樣設計的修改可以爲secondary index節省大量的空間。你能夠把原來設計的主鍵列改爲UNIQUE NOT NULL來強制其的值和主鍵有相同的約束,這樣也就可以阻止重複值或者空值寫入了。

 

If you spread related information across multiple tables, typically each table uses the same column for its primary key. For example, a personnel database might have several tables, each with a primary key of employee number. A sales database might have some tables with a primary key of customer number, and other tables with a primary key of order number. Because lookups using the primary key are very fast, you can construct efficient join queries for such tables.

若是你要在多個表之間傳播相關的信息,一般都會使用相同的列來做爲主鍵。例如,personnel數據庫有不少個表,並且每一個表都有一個員工號來做爲主鍵。sales 數據庫裏部分使用客戶號做爲主鍵,其餘的表用訂單號來做爲主鍵。由於經過主鍵的查詢是很是快速的,因此你可使用這些列來構造高效的join查詢。

 

If you leave the PRIMARY KEY clause out entirely, MySQL creates an invisible one for you. It is a 6-byte value that might be longer than you need, thus wasting space. Because it is hidden, you cannot refer to it in queries.

若是你沒有顯式指定主鍵,那麼MySQL會爲你建立一個隱藏的主鍵。那是一個6-byte的值,遠大於你所須要的,所以會浪費大量的空間。由於是隱藏的,因此你還不能在查詢中使用它。

 

Application Performance Considerations

 

The extra reliability and scalability features of InnoDB do require more disk storage than equivalent MyISAM tables. You might change the column and index definitions slightly, for better space utilization, reduced I/O and memory consumption when processing result sets, and better query optimization plans making efficient use of index lookups.

InnoDB額外的可靠性和可擴展性會比MyISAM要求更多的磁盤空間。你能夠稍微修改列和索引的定義,這樣在處理結果集的時候能獲得更好空間利用率,減小I/O和內存的消耗,也能讓執行計劃更有效地使用索引。

 

If you do set up a numeric ID column for the primary key, use that value to cross-reference with related values in any other tables, particularly for join queries. For example, rather than accepting a country name as input and doing queries searching for the same name, do one lookup to determine the country ID, then do other queries (or a single join query) to look up relevant information across several tables. Rather than storing a customer or catalog item number as a string of digits, potentially using up several bytes, convert it to a numeric ID for storing and querying. A 4-byte unsigned INT column can index over 4 billion items (with the US meaning of billion: 1000 million). For the ranges of the different integer types, see Section 11.2.1, "Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT".

若是你創建一個數字ID列做爲主鍵,那麼就用這列做爲和其餘表進行join的join列。例如,相對於使用country name來進行join,使用country ID來做爲join條件更好。字符串類型的數字,會消耗更多的空間,更好的辦法是使用數值的的數字。一個4-byte unsigned INT列最大可以到4294967295。對於不一樣整數類型的範圍,能夠查看Section 11.2.1, "Integer Types (Exact Value) - INTEGER, INT, SMALLINT, TINYINT, MEDIUMINT, BIGINT"。

 

Understand Files Associated with InnoDB Tables

 

InnoDB files require more care and planning than MyISAM files do:

相對於MyISAM文件,InnoDB的文件須要更多的關注和規劃:

 

  • You must not delete the ibdata files that represent the InnoDB system tablespace.
  • 你不能刪除表明InnoDB系統表空間的ibdata文件。

 

  • Copying InnoDB tables from one server to another requires issuing the FLUSH TABLES ... FOR EXPORT statement first, and copying the table_name.cfg file along with the table_name.ibd file.
  • 從一個實例上覆制InnoDB表到另外一個實例上須要首先執行FLUSH TABLES ... FOR EXPORT,而後再拷貝table_name.cfg和table_name.ibd文件。

 

14.6.5 AUTO_INCREMENT Handling in InnoDB

 

InnoDB provides a configurable locking mechanism that can significantly improve scalability and performance of SQL statements that add rows to tables with AUTO_INCREMENT columns. To use the AUTO_INCREMENT mechanism with an InnoDB table, an AUTO_INCREMENT column must be defined as part of an index such that it is possible to perform the equivalent of an indexed SELECT MAX(ai_col) lookup on the table to obtain the maximum column value. Typically, this is achieved by making the column the first column of some table index.

在添加新的數據行到AUTO_INCREMENT列的時候,InnoDB提供了一種可配置的鎖機制,能夠顯著改善SQL語句的可擴展性和性能。要在InnoDB表上使用AUTO_INCREMENT的機制,AUTO_INCREMENT列必需要被定義成索引的一部分,這樣就可以執行等價於SELECT MAX(ai_col)的查詢來查找這列的最大值。一般,還要把這列做爲索引的第一個列(前綴列)。

 

This section describes the behavior of AUTO_INCREMENT lock modes, usage implications for different AUTO_INCREMENT lock mode settings, and how InnoDB initializes the AUTO_INCREMENT counter.

這章講述了AUTO_INCREMENT行爲的鎖模式,不一樣AUTO_INCREMENT鎖模式設定的使用影響,以及InnoDB如何初始化AUTO_INCREMENT計數器。

 

 

 

 

InnoDB AUTO_INCREMENT Lock Modes

 

This section describes the behavior of AUTO_INCREMENT lock modes used to generate auto-increment values, and how each lock mode affects replication. Auto-increment lock modes are configured at startup using the innodb_autoinc_lock_mode configuration parameter.

這一章節講述了AUTO_INCREMENT的鎖模式,以及每一個鎖模式是如何影響主從複製的。AUTO_INCREMENT的鎖模式能夠在實例啓動的時候經過innodb_autoinc_lock_mode配置參數來設定。

 

The following terms are used in describing innodb_autoinc_lock_mode settings:

下面的內容描述了innodb_autoinc_lock_mode的設定:

 

  • "INSERT-like" statements

 

All statements that generate new rows in a table, including INSERT, INSERT ... SELECT, REPLACE, REPLACE ... SELECT, and LOAD DATA. Includes "simple-inserts", "bulk-inserts", and "mixed-mode" inserts.

生成新數據行的全部語句,包括INSERT, INSERT ... SELECT, REPLACE, REPLACE ... SELECT, and LOAD DATA。也包括"simple-inserts", "bulk-inserts", and "mixed-mode"。

 

  • "Simple inserts"

 

Statements for which the number of rows to be inserted can be determined in advance (when the statement is initially processed). This includes single-row and multiple-row INSERT and REPLACE statements that do not have a nested subquery, but not INSERT ... ON DUPLICATE KEY UPDATE.

語句要插入的行數能夠提早確認(語句預先處理)。這包括了單行或者多行的INSERT,以及沒有嵌套子查詢的REPLACE 語句,可是不包括INSERT ... ON DUPLICATE KEY UPDATE。

 

  • "Bulk inserts"

 

Statements for which the number of rows to be inserted (and the number of required auto-increment values) is not known in advance. This includes INSERT ... SELECT, REPLACE ... SELECT, and LOAD DATA statements, but not plain INSERT. InnoDB will assign new values for the AUTO_INCREMENT column one at a time as each row is processed.

語句要插入的行數(以及要自增加數的數量)預先是未知的。這包括了INSERT ... SELECT, REPLACE ... SELECT, and LOAD DATA ,可是不包括普通的INSERT。InnoDB會爲AUTO_INCREMENT列每一行處理一次地分配新值。

 

  • "Mixed-mode inserts"

 

These are "simple insert" statements that specify the auto-increment value for some (but not all) of the new rows. An example follows, where c1 is an AUTO_INCREMENT column of table t1:

這是爲新的行(但不是全部)指定自增加值的"simple insert"語句。例以下面的例子,c1是t1表的AUTO_INCREMENT列:

 

INSERT INTO t1 (c1,c2) VALUES (1,'a'), (NULL,'b'), (5,'c'), (NULL,'d');

 

Another type of "mixed-mode insert" is INSERT ... ON DUPLICATE KEY UPDATE, which in the worst case is in effect an INSERT followed by a UPDATE, where the allocated value for the AUTO_INCREMENT column may or may not be used during the update phase.

INSERT ... ON DUPLICATE KEY UPDATE是另外一種類型的"mixed-mode insert",實際上最壞的狀況是INSERT後面緊跟着UPDATE,這樣爲AUTO_INCREMENT分配的值可能在update階段沒法使用。

 

There are three possible settings for the innodb_autoinc_lock_mode configuration parameter. The settings are 0, 1, or 2, for "traditional", "consecutive", or "interleaved" lock mode, respectively.

innodb_autoinc_lock_mode配置參數有三種可能的設定,分別是0, 1, or 2,分別對應"traditional(傳統的)", "consecutive(連續的)", or "interleaved(交錯的)"鎖模式。

 

  • innodb_autoinc_lock_mode = 0 ("traditional" lock mode)

 

The traditional lock mode provides the same behavior that existed before the innodb_autoinc_lock_mode configuration parameter was introduced in MySQL 5.1. The traditional lock mode option is provided for backward compatibility, performance testing, and working around issues with "mixed-mode inserts", due to possible differences in semantics.

傳統的鎖模式提供了自MySQL5.1引進innodb_autoinc_lock_mode以前已存在相同的行爲。傳統鎖模式主要用於向後兼容,性能測試,以及因爲可能的有語義問題的"mixed-mode inserts"。

 

In this lock mode, all "INSERT-like" statements obtain a special table-level AUTO-INC lock for inserts into tables with AUTO_INCREMENT columns. This lock is normally held to the end of the statement (not to the end of the transaction) to ensure that auto-increment values are assigned in a predictable and repeatable order for a given sequence of INSERT statements, and to ensure that auto-increment values assigned by any given statement are consecutive.

在這種鎖模式下,全部的"INSERT-like"語句都包含了一個特別的表級別的AUTO-INC鎖,用於往AUTO_INCREMENT列插入數據。這個鎖一般會保持到語句結束(不是事務結束)來確保分配的自增加的值是可預測的,以及對於給定順序的INSERT語句的順序是可重現的,還有要確保對於給定語句分配的自增加值是連續的。

 

In the case of statement-based replication, this means that when an SQL statement is replicated on a slave server, the same values are used for the auto-increment column as on the master server. The result of execution of multiple INSERT statements is deterministic, and the slave reproduces the same data as on the master. If auto-increment values generated by multiple INSERT statements were interleaved, the result of two concurrent INSERT statements would be nondeterministic, and could not reliably be propagated to a slave server using statement-based replication.

在基於語句(statement-based)的主從複製狀況下,這也就意味着當一個SQL語句重複到slave端的時候,自增加列的值會和master端的相同。多個INSERT語句的執行結果是肯定的,slave端產生的值會和master端相同。若是多ISNERT語句生成的自增加值是交錯的,兩個併發的INSERT語句產生的結果是不肯定的,那就不能使用基於語句的主從複製把結果可靠地傳播到slave端上。

 

To make this clear, consider an example that uses this table:

爲了更清楚說明狀況,能夠查看下面的例子:

 

CREATE TABLE t1 (

c1 INT(11) NOT NULL AUTO_INCREMENT,

c2 VARCHAR(10) DEFAULT NULL,

PRIMARY KEY (c1)

) ENGINE=InnoDB;

 

Suppose that there are two transactions running, each inserting rows into a table with an AUTO_INCREMENT column. One transaction is using an INSERT ... SELECT statement that inserts 1000 rows, and another is using a simple INSERT statement that inserts one row:

假設有兩個事務正在運行,每一個都往表裏插入自增加值。一個事務使用INSERT ... SELECT插入1000行記錄,另外一個使用簡單的INSERT語句插入一行記錄:

 

Tx1: INSERT INTO t1 (c2) SELECT 1000 rows from another table ...

Tx2: INSERT INTO t1 (c2) VALUES ('xxx');

 

InnoDB cannot tell in advance how many rows will be retrieved from the SELECT in the INSERT statement in Tx1, and it assigns the auto-increment values one at a time as the statement proceeds. With a table-level lock, held to the end of the statement, only one INSERT statement referring to table t1 can execute at a time, and the generation of auto-increment numbers by different statements is not interleaved. The auto-increment value generated by the Tx1 INSERT ... SELECT statement will be consecutive, and the (single) auto-increment value used by the INSERT statement in Tx2 will either be smaller or larger than all those used for Tx1, depending on which statement executes first.

在Tx1裏面InnoDB不會預先告訴你INSERT語句裏面的SELECT會檢索多少行的記錄,它會在語句處理過程當中每次一個分配自增加值。這個表級的鎖會保持到語句結束,一次執行只執行一個INSERT語句,那麼不一樣的語句產生的自增加值就不會是交錯的。Tx1 INSERT ... SELECT產生的自增加值將會是連續的,而Tx2的自增加值只會小於或者大於Tx1生產的值,只取決於哪一個語句先實行。

 

As long as the SQL statements execute in the same order when replayed from the binary log (when using statement-based replication, or in recovery scenarios), the results will be the same as they were when Tx1 and Tx2 first ran. Thus, table-level locks held until the end of a statement make INSERT statements using auto-increment safe for use with statement-based replication. However, those table-level locks limit concurrency and scalability when multiple transactions are executing insert statements at the same time.

在從binary log重現的時候(使用基於語句的主從複製,或者恢復場景中)只要SQL語句是以相同的順序執行的,那麼結果集合Tx1 and Tx2運行的順序同樣。所以,保持到語句結束的表級鎖使得在基於主從複製中INSERT語句使用自增加更爲安全。然而,當多個事務在同一個時間點指定insert的時候,這些表級鎖也限制了併發性和可擴展性。

 

In the preceding example, if there were no table-level lock, the value of the auto-increment column used for the INSERT in Tx2 depends on precisely when the statement executes. If the INSERT of Tx2 executes while the INSERT of Tx1 is running (rather than before it starts or after it completes), the specific auto-increment values assigned by the two INSERT statements are nondeterministic, and may vary from run to run.

在上面的例子裏,若是沒有表級鎖,那麼Tx2裏的INSERT的自增加值就要取決於語句執行的準確時間。若是Tx2的INSERT執行的時候Tx1的INSERT正在運行(不是在它開始以前或者完成以後),這兩個INSERT語句分配的自增加值將會是非肯定性的,幾回運行之間也可能會不一樣。

 

Under the consecutive lock mode, InnoDB can avoid using table-level AUTO-INC locks for "simple insert" statements where the number of rows is known in advance, and still preserve deterministic execution and safety for statement-based replication.

在連續鎖(consecutive )模式下面,InnoDB會避免對"simple insert"語句使用表級別的AUTO-INC鎖,由於它們產生的新行數是可預期的,但對於基於語句的主從複製仍是會保持執行語句的肯定性和安全性。

 

If you are not using the binary log to replay SQL statements as part of recovery or replication, the interleaved lock mode can be used to eliminate all use of table-level AUTO-INC locks for even greater concurrency and performance, at the cost of permitting gaps in auto-increment numbers assigned by a statement and potentially having the numbers assigned by concurrently executing statements interleaved.

若是你沒有使用使用binary log重現SQL來做爲恢復或者主從複製的一部分,交錯的(interleaved )鎖模式能夠用於消除全部的表級AUTO-INC鎖,並以此得到更高的併發性和性能。這種狀況會容許在語句生成的自增加值上有間隙,由於併發執行的語句多是交錯執行的。

 

  • innodb_autoinc_lock_mode = 1 ("consecutive" lock mode)

 

This is the default lock mode. In this mode, "bulk inserts" use the special AUTO-INC table-level lock and hold it until the end of the statement. This applies to all INSERT ... SELECT, REPLACE ... SELECT, and LOAD DATA statements. Only one statement holding the AUTO-INC lock can execute at a time.

這是默認的鎖模式。在這種模式下,"bulk inserts"會使用特殊的AUTO-INC表級鎖,並保持到語句執行結束。這適用於全部的INSERT ... SELECT, REPLACE ... SELECT, and LOAD DATA語句。同一個時間點上只有一個語句持有AUTO-INC鎖來執行。

 

"Simple inserts" (for which the number of rows to be inserted is known in advance) avoid table-level AUTO-INC locks by obtaining the required number of auto-increment values under the control of a mutex (a light-weight lock) that is only held for the duration of the allocation process, not until the statement completes. No table-level AUTO-INC lock is used unless an AUTO-INC lock is held by another transaction. If another transaction holds an AUTO-INC lock, a "simple insert" waits for the AUTO-INC lock, as if it were a "bulk insert".

"Simple inserts"(插入行的數量是可預期的)經過在一個mutex的控制下或者要求的自增加值的數量來避免表級別的AUTO-INC鎖。這個mutex只會才分配的過程當中持有,不須要等到語句結束。除非另外一個事務持有了一個 AUTO-INC鎖,那麼InnoDB將不會使用表級別的 AUTO-INC鎖。若是另外一個事務持有了 AUTO-INC鎖,"simple insert"將會等待AUTO-INC鎖,就如"bulk insert"同樣。

 

This lock mode ensures that, in the presence of INSERT statements where the number of rows is not known in advance (and where auto-increment numbers are assigned as the statement progresses), all auto-increment values assigned by any "INSERT-like" statement are consecutive, and operations are safe for statement-based replication.

這種模式會確保在面對不能預知插入行的數量(語句分配自增加值的數量)的INSERT的語句的時候,任何"INSERT-like"語句分配的 全部自增加值都是連續的,對於基於語句複製的主從複製的操做是安全的。

 

Simply put, this lock mode significantly improves scalability while being safe for use with statement-based replication. Further, as with "traditional" lock mode, auto-increment numbers assigned by any given statement are consecutive. There is no change in semantics compared to "traditional" mode for any statement that uses auto-increment, with one important exception.

簡而言之,對於使用基於語句的主從複製環境,這種鎖模式不只可以保證安全性,還能顯著改善可擴展性。更進一步地說,和"traditional"鎖模式同樣,任何語句分配的自增加值都是連續的。對於任何使用自增加的語句來講,這和"traditional"模式在語義上是沒有改變的,只有有一個重要的例外。

 

The exception is for "mixed-mode inserts", where the user provides explicit values for an AUTO_INCREMENT column for some, but not all, rows in a multiple-row "simple insert". For such inserts, InnoDB allocates more auto-increment values than the number of rows to be inserted. However, all values automatically assigned are consecutively generated (and thus higher than) the auto-increment value generated by the most recently executed previous statement. "Excess" numbers are lost.

這個例外是針對"mixed-mode inserts"的。這種狀況下用戶會爲自增加列提供一些明確的值,但又不是所有的。對於這樣insert語句,InnoDB會分配比插入行數更多的自增加值。但是,全部自動分配的值都是連續產生的,所以要比由最近上次執行的語句生成的自增加值要多。"超出"的數值將會被丟棄。

 

  • innodb_autoinc_lock_mode = 2 ("interleaved" lock mode)

 

In this lock mode, no "INSERT-like" statements use the table-level AUTO-INC lock, and multiple statements can execute at the same time. This is the fastest and most scalable lock mode, but it is not safe when using statement-based replication or recovery scenarios when SQL statements are replayed from the binary log.

在這種鎖模式下,沒有"INSERT-like"語句會使用表級別的AUTO-INC鎖,同一個時間點上也能執行多個語句。這是最快的,也是最易升級的鎖模式,可是在使用基於語句的主從複製或者恢復場景中從binary log進行基於語句的重現將會是不安全的。

 

In this lock mode, auto-increment values are guaranteed to be unique and monotonically increasing across all concurrently executing "INSERT-like" statements. However, because multiple statements can be generating numbers at the same time (that is, allocation of numbers is interleaved across statements), the values generated for the rows inserted by any given statement may not be consecutive.

在這種鎖模式下,併發執行的"INSERT-like"語句產生的自增加值是惟一單調遞增的。然而,由於在同一個時間上會有多個語句生成值(也就是說多個語句分配的值是交錯的),那語句插入行生成的值就可能會是不連續的。

 

If the only statements executing are "simple inserts" where the number of rows to be inserted is known ahead of time, there will be no gaps in the numbers generated for a single statement, except for "mixed-mode inserts". However, when "bulk inserts" are executed, there may be gaps in the auto-increment values assigned by any given statement.

若是隻會執行"simple inserts"(插入行的數量預先可知的)語句,除非是mixed-mode inserts",那麼對於單個語句生成的數值是不會有間隙的。然而,當執行了"bulk inserts",那麼語句分配的自增加值就可能會有間隙了。

 

InnoDB AUTO_INCREMENT Lock Mode Usage Implications

 

  • Using auto-increment with replication
  • 主從複製中使用自增加

 

If you are using statement-based replication, set innodb_autoinc_lock_mode to 0 or 1 and use the same value on the master and its slaves. Auto-increment values are not ensured to be the same on the slaves as on the master if you use innodb_autoinc_lock_mode = 2 ("interleaved") or configurations where the master and slaves do not use the same lock mode.

若是你使用基於語句的主從複製,innodb_autoinc_lock_mode的值爲0或1可讓主從端有相同的值。若是innodb_autoinc_lock_mode = 2 ("interleaved")或者主從端使用了不一樣的鎖模式的時候,則就不能確保主從端的自增加值相同。

 

If you are using row-based or mixed-format replication, all of the auto-increment lock modes are safe, since row-based replication is not sensitive to the order of execution of the SQL statements (and the mixed format uses row-based replication for any statements that are unsafe for statement-based replication).

若是你使用基於行(row-based)或者混合模式(mixed-format)的主從複製,全部的自增加鎖模式都是安全的,由於基於行的主從複製(row-based replication)不受SQL語句執行順序的影響(對於基於語句的主從複製中不安全的語句,混合模式會使用基於行的主從複製)。

 

  • "Lost" auto-increment values and sequence gaps
  • "丟失"自增加值和序列空位

 

In all lock modes (0, 1, and 2), if a transaction that generated auto-increment values rolls back, those auto-increment values are "lost". Once a value is generated for an auto-increment column, it cannot be rolled back, whether or not the "INSERT-like" statement is completed, and whether or not the containing transaction is rolled back. Such lost values are not reused. Thus, there may be gaps in the values stored in an AUTO_INCREMENT column of a table.

在全部的鎖模式中(0, 1, and 2),若是一個事務裏產生了自增加值,但這個事務回滾了,那麼這些自增加值也就"丟失"了。一旦自增加列生成了值,那這個值是不能被回滾掉的,不論這個"INSERT-like"語句是否完成,也不會管這個事務時不會被會滾了。這些丟失的值是補充從新利用的,所以,表的自增加列上存儲的值是有可能有間隙的。

 

  • Specifying NULL or 0 for the AUTO_INCREMENT column
  • 爲AUTO_INCREMENT列指定NULL或者0

 

In all lock modes (0, 1, and 2), if a user specifies NULL or 0 for the AUTO_INCREMENT column in an INSERT, InnoDB treats the row as if the value was not specified and generates a new value for it.

在全部的鎖模式裏(0, 1, and 2),若是在INSERT裏面爲AUTO_INCREMENT列指定NULL或者0,InnoDB就會像沒指定值同樣生成新值。

 

  • Assigning a negative value to the AUTO_INCREMENT column
  • 爲AUTO_INCREMENT分配一個負值

 

In all lock modes (0, 1, and 2), the behavior of the auto-increment mechanism is not defined if you assign a negative value to the AUTO_INCREMENT column.

在全部的鎖模式裏(0, 1, and 2),若是你爲AUTO_INCREMENT列分配一個負值,那麼自增加機制就不會工做(不會分配新值)。

 

  • If the AUTO_INCREMENT value becomes larger than the maximum integer for the specified integer type
  • 若是AUTO_INCREMENT值開始大於指定的整數類型的最大值

 

In all lock modes (0, 1, and 2), the behavior of the auto-increment mechanism is not defined if the value becomes larger than the maximum integer that can be stored in the specified integer type.

在全部的鎖模式裏(0, 1, and 2),若是自增加值開始大於定義的整數類型的最大值,那麼自增加機制就不工做了。

 

  • Gaps in auto-increment values for "bulk inserts"
  • "bulk inserts"中自增加值的間隙

 

With innodb_autoinc_lock_mode set to 0 ("traditional") or 1 ("consecutive"), the auto-increment values generated by any given statement will be consecutive, without gaps, because the table-level AUTO-INC lock is held until the end of the statement, and only one such statement can execute at a time.

當innodb_autoinc_lock_mode被設置成0 ("traditional") or 1 ("consecutive")的時候,任何語句產生的自增加值都會是連續的,沒有間隙,由於表級別的AUTO-INC鎖會被持有到語句執行結束,但同一時間點也就只能有一個語句能被執行。

 

With innodb_autoinc_lock_mode set to 2 ("interleaved"), there may be gaps in the auto-increment values generated by "bulk inserts," but only if there are concurrently executing "INSERT-like" statements.

當innodb_autoinc_lock_mode被設置成2 ("interleaved"),那麼"bulk inserts,"就有可能產生有間隙的自增加值,但也只有在併發執行"INSERT-like"語句時候纔會發生。

 

For lock modes 1 or 2, gaps may occur between successive statements because for bulk inserts the exact number of auto-increment values required by each statement may not be known and overestimation is possible.

對於1 or 2的鎖模式來講,連續的語句是可能發生間隙的,由於批量插入的每一個語句要求的確切的自增加值的數量是不可知的,只能進行過量估計。

 

  • Auto-increment values assigned by "mixed-mode inserts"
  • "mixed-mode inserts"分配的自增加值

 

Consider a "mixed-mode insert," where a "simple insert" specifies the auto-increment value for some (but not all) resulting rows. Such a statement will behave differently in lock modes 0, 1, and 2. For example, assume c1 is an AUTO_INCREMENT column of table t1, and that the most recent automatically generated sequence number is 100.

要考慮一種"mixed-mode insert"的狀況:其中一個"simple insert"語句爲在結果集中部分指定了自增加列的確切的值,但又不是所有的。這種狀況徹底不一樣於0, 1, and 2的鎖模式。例如,假設t1表有自增加列c1,最近自動生成的自增加序號是100。

 

mysql> CREATE TABLE t1 (

-> c1 INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,

-> c2 CHAR(1)

-> ) ENGINE = INNODB;

 

mysql> INSERT INTO t1 VALUES(1,'a'),(101,'b'),(5,'c'),(102,'d');

 

Now, consider the following "mixed-mode insert" statement:

如今考慮一下下面的"mixed-mode insert"語句:

 

mysql> INSERT INTO t1 (c1,c2) VALUES (1,'a'), (NULL,'b'), (5,'c'), (NULL,'d');

 

With innodb_autoinc_lock_mode set to 0 ("traditional"), the four new rows will be:

當innodb_autoinc_lock_mode=0("traditional")的時候,四行新記錄將會是:

 

mysql> SELECT c1, c2 FROM t1 ORDER BY c2;

+-----+------+

| c1 | c2 |

+-----+------+

| 1 | a |

| 101 | b |

| 5 | c |

| 102 | d |

+-----+------+

 

The next available auto-increment value will be 103 because the auto-increment values are allocated one at a time, not all at once at the beginning of statement execution. This result is true whether or not there are concurrently executing "INSERT-like" statements (of any type).

下一個自增加值將是103,由於這些自增加值是每次分配一個的,並非全部的都在語句開始執行的時候分配的。不管是否併發執行了"INSERT-like"語句結果都是這樣的。

 

With innodb_autoinc_lock_mode set to 1 ("consecutive"), the four new rows will also be:

當innodb_autoinc_lock_mode=1("consecutive")的時候,新的四行記錄也是同樣的:

 

mysql> SELECT c1, c2 FROM t1 ORDER BY c2;

+-----+------+

| c1 | c2 |

+-----+------+

| 1 | a |

| 101 | b |

| 5 | c |

| 102 | d |

+-----+------+

 

However, in this case, the next available auto-increment value will be 105, not 103 because four auto-increment values are allocated at the time the statement is processed, but only two are used. This result is true whether or not there are concurrently executing "INSERT-like" statements (of any type).

然而,在這種狀況下,下一個自增加值將會是105,而不是103,由於在語句處理的時候已經分配了四個自增加值,但只是用了兩個。不管是否併發執行了"INSERT-like"語句結果都是這樣的。

 

With innodb_autoinc_lock_mode set to mode 2 ("interleaved"), the four new rows will be:

當innodb_autoinc_lock_mode=2("interleaved"),新的四行記錄將會是:

 

mysql> SELECT c1, c2 FROM t1 ORDER BY c2;

+-----+------+

| c1 | c2 |

+-----+------+

| 1 | a |

| x | b |

| 5 | c |

| y | d |

+-----+------+

 

The values of x and y will be unique and larger than any previously generated rows. However, the specific values of x and y will depend on the number of auto-increment values generated by concurrently executing statements.

這裏面的x,y都是惟一的,並且會比以前生成的要大。但是,這些特定的x,y也是要依賴於來併發執行語句生成自增加值的數量的。

 

Finally, consider the following statement, issued when the most-recently generated sequence number was the value 4:

最後,考慮一下下面的語句,這句執行的時候最近生成的序號數是4:

 

mysql> INSERT INTO t1 (c1,c2) VALUES (1,'a'), (NULL,'b'), (5,'c'), (NULL,'d');

 

With any innodb_autoinc_lock_mode setting, this statement will generate a duplicate-key error 23000 (Can't write; duplicate key in table) because 5 will be allocated for the row (NULL, 'b') and insertion of the row (5, 'c') will fail.

不管innodb_autoinc_lock_mode的設置是什麼,這個語句都會報重複鍵error 23000 的錯誤,由於(NULL, 'b')會分配到5,而 (5, 'c') 的插入就會失敗。

 

  • Modifying AUTO_INCREMENT column values in the middle of a sequence of INSERT statements
  • 在一些列INSERT語句的中間修改AUTO_INCREMENT列的值

 

In all lock modes (0, 1, and 2), modifying an AUTO_INCREMENT column value in the middle of a sequence of INSERT statements could lead to "Duplicate entry" errors. For example, if you perform an UPDATE operation that changes an AUTO_INCREMENT column value to a value larger than the current maximum auto-increment value, subsequent INSERT operations that do not specify an unused auto-increment value could encounter "Duplicate entry" errors. This behavior is demonstrated in the following example.

在全部的鎖模式中(0, 1, and 2),在一系列INSERT語句中間修改AUTO_INCREMENT列的值將會致使"Duplicate entry"錯誤。例如,若是你執行了一個UPDATE操做把AUTO_INCREMENT列的值修改的超過當前自增加的最大值了,那麼隨後沒有指定自增加值的INSERT操做就會遭遇到"Duplicate entry"錯誤。下面的例子演示了這種狀況。

 

mysql> CREATE TABLE t1 (

-> c1 INT NOT NULL AUTO_INCREMENT,

-> PRIMARY KEY (c1)

-> ) ENGINE = InnoDB;

 

mysql> INSERT INTO t1 VALUES(0), (0), (3);

 

mysql> SELECT c1 FROM t1;

+----+

| c1 |

+----+

| 1 |

| 2 |

| 3 |

+----+

 

mysql> UPDATE t1 SET c1 = 4 WHERE c1 = 1;

 

mysql> SELECT c1 FROM t1;

+----+

| c1 |

+----+

| 2 |

| 3 |

| 4 |

+----+

 

mysql> INSERT INTO t1 VALUES(0);

ERROR 1062 (23000): Duplicate entry '4' for key 'PRIMARY'

 

InnoDB AUTO_INCREMENT Counter Initialization

 

This section describes how InnoDB initializes AUTO_INCREMENT counters.

這部分講述了InnoDB如何初始化AUTO_INCREMENT計數器。

 

If you specify an AUTO_INCREMENT column for an InnoDB table, the table handle in the InnoDB data dictionary contains a special counter called the auto-increment counter that is used in assigning new values for the column. This counter is stored only in main memory, not on disk.

若是你爲InnoDB表指定了一個AUTO_INCREMENT列,InnoDB在數據字典裏就會包含一個稱之爲auto-increment的計數器,用於爲AUTO_INCREMENT列分配新值。這個計數器只存儲在主內存裏,而不是在磁盤上。

 

To initialize an auto-increment counter after a server restart, InnoDB executes the equivalent of the following statement on the first insert into a table containing an AUTO_INCREMENT column.

在實例重啓以後爲了初始化一個auto-increment counter,InnoDB會在AUTO_INCREMENT列插入的時候執行等價於下面的語句。

 

SELECT MAX(ai_col) FROM table_name FOR UPDATE;

 

InnoDB increments the value retrieved by the statement and assigns it to the column and to the auto-increment counter for the table. By default, the value is incremented by 1. This default can be overridden by the auto_increment_increment configuration setting.

InnoDB會增長語句返回的值,而後將其分配到列以及auto-increment counter上。默認狀況下,遞增的值是1。這個默認值是能夠被auto_increment_increment配置參數覆蓋的。

 

If the table is empty, InnoDB uses the value 1. This default can be overridden by the auto_increment_offset configuration setting.

若是表是空的,InnoDB使用的值是1。這個默認值是能夠被auto_increment_offset配置參數覆蓋的。

 

If a SHOW TABLE STATUS statement examines the table before the auto-increment counter is initialized, InnoDB initializes but does not increment the value. The value is stored for use by later inserts. This initialization uses a normal exclusive-locking read on the table and the lock lasts to the end of the transaction. InnoDB follows the same procedure for initializing the auto-increment counter for a newly created table.

若是在初始化auto-increment counter初始化以前執行了SHOW TABLE STATUS,InnoDB會初始化但不會增長這個值。這個值會被存儲起來以供後來insert使用。這個初始化的操做會在表上加一個排他的讀鎖直到事務結束。對於最新建立的表InnoDB也是以一樣的方式處理auto-increment counter的。

 

After the auto-increment counter has been initialized, if you do not explicitly specify a value for an AUTO_INCREMENT column, InnoDB increments the counter and assigns the new value to the column. If you insert a row that explicitly specifies the column value, and the value is greater than the current counter value, the counter is set to the specified column value.

在auto-increment counter被初始化以後,若是你沒有爲AUTO_INCREMENT列明確指定一個 值,那麼InnoDB會增長這個計數器併爲列分配一個新增。若是你插入的時候明確指定了值,而且這個值大於當前的counter值,那counter將會被設定爲這個指定的值。

 

InnoDB uses the in-memory auto-increment counter as long as the server runs. When the server is stopped and restarted, InnoDB reinitializes the counter for each table for the first INSERT to the table, as described earlier.

只要實例在運行,InnoDB會在內存裏使用auto-increment counter。當實例關閉和重啓的時候,InnoDB爲每張表的第一個INSERT從新初始化counter,就如前面所說的。

 

A server restart also cancels the effect of the AUTO_INCREMENT = N table option in CREATE TABLE and ALTER TABLE statements, which you can use with InnoDB tables to set the initial counter value or alter the current counter value.

實例重啓會取消當時CREATE TABLE and ALTER TABLE語句中AUTO_INCREMENT = N的影響。

 

14.6.6 InnoDB and FOREIGN KEY Constraints

 

This section describes differences in the InnoDB storage engine's handling of foreign keys as compared with that of the MySQL Server.

這一部分講述了InnoDB在處理外鍵上和其餘引擎之間的不一樣之處。

 

Foreign Key Definitions

 

Foreign key definitions for InnoDB tables are subject to the following conditions:

InnoDB對於外鍵的定義有下面幾條:

 

  • InnoDB permits a foreign key to reference any index column or group of columns. However, in the referenced table, there must be an index where the referenced columns are listed as the first columns in the same order.
  • InnoDB容許外鍵引用任何的索引中的單個列或者一組列。然而,在引用的表裏,必需要索引列的順序要和外鍵列的順序同樣。

 

  • InnoDB does not currently support foreign keys for tables with user-defined partitioning. This means that no user-partitioned InnoDB table may contain foreign key references or columns referenced by foreign keys.
  • 目前分區表還不支持外鍵。

 

  • InnoDB allows a foreign key constraint to reference a non-unique key. This is an InnoDB extension to standard SQL.
  • InnoDB容許外鍵引向一個非惟一的索引。這是InnoDB對於標準SQL的一個擴展。

 

Referential Actions

 

Referential actions for foreign keys of InnoDB tables are subject to the following conditions:

InnoDB外鍵的referential actions有下面幾條:

 

  • While SET DEFAULT is allowed by the MySQL Server, it is rejected as invalid by InnoDB. CREATE TABLE and ALTER TABLE statements using this clause are not allowed for InnoDB tables.
  • 當MySQL容許SET DEFAULT的時候,InnoDB會拒絕無效的。InnoDB不容許在CREATE TABLE and ALTER TABLE使用這個子句。

 

  • If there are several rows in the parent table that have the same referenced key value, InnoDB acts in foreign key checks as if the other parent rows with the same key value do not exist. For example, if you have defined a RESTRICT type constraint, and there is a child row with several parent rows, InnoDB does not permit the deletion of any of those parent rows.
  • 若是在父表裏好幾行數據有着相同的referenced key值,InnoDB外鍵會檢查是否有其餘的parent row有相同的key值。例如,你定義了一個RESTRICT類型的約束,而且有個child row有好幾個parent row,那麼InnoDB將不會容許刪除這些parent row中的任何一個。

 

  • InnoDB performs cascading operations through a depth-first algorithm, based on records in the indexes corresponding to the foreign key constraints.
  • InnoDB會經過depth-first算法,基於對應外鍵的索引的記錄來執行串聯的操做,

 

  • If ON UPDATE CASCADE or ON UPDATE SET NULL recurses to update the same table it has previously updated during the cascade, it acts like RESTRICT. This means that you cannot use self-referential ON UPDATE CASCADE or ON UPDATE SET NULL operations. This is to prevent infinite loops resulting from cascaded updates. A self-referential ON DELETE SET NULL, on the other hand, is possible, as is a self-referential ON DELETE CASCADE. Cascading operations may not be nested more than 15 levels deep.
  • 若是ON UPDATE CASCADE or ON UPDATE SET NULL遞歸更新相同的表,那麼在串聯的時候與預先update,就像RESTRICT。這意味着你不能使用自我引用的ON UPDATE CASCADE or ON UPDATE SET NULL操做。這是爲了從串聯更新中阻止死循環。另外一方面,自我引用的ON DELETE SET NULL是可行的,就如同自我引用的ON DELETE CASCADE同樣。串聯操做不能超過15層的嵌套循環。

 

  • Like MySQL in general, in an SQL statement that inserts, deletes, or updates many rows, InnoDB checks UNIQUE and FOREIGN KEY constraints row-by-row. When performing foreign key checks, InnoDB sets shared row-level locks on child or parent records it has to look at. InnoDB checks foreign key constraints immediately; the check is not deferred to transaction commit. According to the SQL standard, the default behavior should be deferred checking. That is, constraints are only checked after the entire SQL statement has been processed. Until InnoDB implements deferred constraint checking, some things will be impossible, such as deleting a record that refers to itself using a foreign key.
  • 和普通的MySQL同樣,在一個操做多行的DML語句裏面,InnoDB會逐行檢查惟一和外鍵約束。當執行外鍵檢查的時候,InnoDB會子查看的child或者parnet記錄上放置一個行級的共享鎖。InnoDB會當即檢查外鍵約束;這個檢查也不會延遲到事務提交。可是在SQL標準裏面,默認的是爲進行延遲檢查的。那就是說,只有在完整的SQL處理完以後纔會進行約束檢查。直到InnoDB落實了約束延遲檢查,一些事情也就不會發生了,例如刪除一個使用外鍵引向其自身的記錄。

 

Foreign Key Usage and Error Information

 

You can obtain general information about foreign keys and their usage from querying the INFORMATION_SCHEMA.KEY_COLUMN_USAGE table, and more information more specific to InnoDB tables can be found in the INNODB_SYS_FOREIGN and INNODB_SYS_FOREIGN_COLS tables, also in the INFORMATION_SCHEMA database. See also Section 13.1.17.3, "Using FOREIGN KEY Constraints".

你能夠經過查詢INFORMATION_SCHEMA.KEY_COLUMN_USAGE表來得到外鍵及其使用的相關信息,InnoDB中更多詳細的信息能夠在INFORMATION_SCHEMA數據庫的INNODB_SYS_FOREIGN和INNODB_SYS_FOREIGN_COLS表裏找到。相關內容可見Section 13.1.17.3, "Using FOREIGN KEY Constraints"。

 

In addition to SHOW ERRORS, in the event of a foreign key error involving InnoDB tables (usually Error 150 in the MySQL Server), you can obtain a detailed explanation of the most recent InnoDB foreign key error by checking the output of SHOW ENGINE INNODB STATUS.

除了SHOW ERRORS以外,在涉及InnoDB表外鍵錯誤(在MySQL裏一般是Error 150)的事件裏,你能夠檢查SHOW ENGINE INNODB STATUS來得到最近的InnoDB外鍵錯誤的詳細解讀。

 

14.6.7 Limits on InnoDB Tables

 

Warning

 

Do not convert MySQL system tables in the mysql database from MyISAM to InnoDB tables. This is an unsupported operation. If you do this, MySQL does not restart until you restore the old system tables from a backup or regenerate them by reinitializing the data directory (see Section 2.10.1, "Initializing the Data Directory").

不要把mysql數據庫裏的系統表從MyISAM轉成InnoDB。這個操做是不支持的。若是你這麼作了,在你從備份裏恢復這些表從新初始化了數據字典以前不要重啓MySQL(詳見2.10.1, "Initializing the Data Directory")。

 

Warning

 

It is not a good idea to configure InnoDB to use data files or log files on NFS volumes. Otherwise, the files might be locked by other processes and become unavailable for use by MySQL.

不要把InnoDB的數據文件或者日誌文件放到NFS捲上。不然,對於MySQL來講這些文件可能會被其餘進程鎖住而變得不可用。

 

Maximums and Minimums

 

  • A table can contain a maximum of 1017 columns (raised in MySQL 5.6.9 from the earlier limit of 1000).
  • 一個表最大能夠有1017個列(從MySQL5.6.9來提高的,之前的限制是1000)。

 

  • A table can contain a maximum of 64 secondary indexes.
  • 一個表最多能夠有64個secondary index。

 

  • By default, an index key for a single-column index can be up to 767 bytes. The same length limit applies to any index key prefix. See Section 13.1.13, "CREATE INDEX Syntax". For example, you might hit this limit with a column prefix index of more than 255 characters on a TEXT or VARCHAR column, assuming a UTF-8 character set and the maximum of 3 bytes for each character. When the innodb_large_prefix configuration option is enabled, this length limit is raised to 3072 bytes, for InnoDB tables that use the DYNAMIC and COMPRESSED row formats.
  • 默認狀況下,單列索引的key最大能夠達到767 bytes。任何索引key的前綴也都有相同的長度限制。相關內容可見Section 13.1.13, "CREATE INDEX Syntax"。例如,假設使用的是UTF-8的字符集,每一個字符最大可以達到3 bytes,那麼在超過255個字符的TEXT或者VARCHAR列的索引前綴上就很容易達到這個限制。對於使用了DYNAMIC and COMPRESSED行格式的InnoDB表來講,當開啓了nnodb_large_prefix配置參數,這個長度的限制能夠達到3072 bytes。

 

Attempting to use an index prefix length that is greater than the allowed maximum value produces an error. To avoid such errors for replication configurations, avoid setting the innodb_large_prefix option on the master if it cannot also be set on the slaves, and the slaves have unique indexes that could be affected by this limit.

假設使用的索引前綴的長度大於了最大容許的值並報了錯。To avoid such errors for replication configurations, avoid setting the innodb_large_prefix option on the master if it cannot also be set on the slaves, and the slaves have unique indexes that could be affected by this limit.

 

  • The InnoDB internal maximum key length is 3500 bytes, but MySQL itself restricts this to 3072 bytes. This limit applies to the length of the combined index key in a multi-column index.
  • InnoDB在內部key的最大長度是3500 bytes,但MySQL約束了這個只能達到3072 bytes。全部多列索引的組合索引key都有這個限制。

 

  • If you reduce the InnoDB page size to 8KB or 4KB by specifying the innodb_page_size option when creating the MySQL instance, the maximum length of the index key is lowered proportionally, based on the limit of 3072 bytes for a 16KB page size. That is, the maximum index key length is 1536 bytes when the page size is 8KB, and 768 bytes when the page size is 4KB.
  • 若是在建立MySQL實例的時候經過指定innodb_page_size參數把InnoDB的數據頁的大小降到了8KB or 4KB,基於16KB頁大小3072 bytes的限制,索引key的最大長度也會成比例地降低。那就是說,當頁大小是8KB的時候最大的索引key的長度是1536 bytes,當也大小是4KB的時候最大索引key的長度是768 bytes。

 

  • The maximum row length, except for variable-length columns (VARBINARY, VARCHAR, BLOB and TEXT), is slightly less than half of a database page. That is, the maximum row length is about 8000 bytes for the default page size of 16KB; if you reduce the page size by specifying the innodb_page_size option when creating the MySQL instance, the maximum row length is 4000 bytes for 8KB pages and 2000 bytes for 4KB pages. LONGBLOB and LONGTEXT columns must be less than 4GB, and the total row length, including BLOB and TEXT columns, must be less than 4GB.
  • 除了可變長度列(VARBINARY, VARCHAR, BLOB and TEXT),行的最大長度會比數據頁的大小的一半再稍微小一點。那就是說,默認的16KB的頁大小,最大的行長度在8000 bytes左右;若是你在建立MySQL實例的時候經過innodb_page_size減小了頁的大小,那麼8KB的頁對應的是限制是4000 bytes,4KB的頁大小對應的是2000 bytes。另外LONGBLOB and LONGTEXT列必須小於4GB,還有包括BLOB and TEXT在內的全部的行長度必須小於4GB。

 

If a row is less than half a page long, all of it is stored locally within the page. If it exceeds half a page, variable-length columns are chosen for external off-page storage until the row fits within half a page, as described in Section 14.10.2, "File Space Management".

若是一個行的長度不到頁大小的一半,那麼它的所有內容都會被存儲在這個數據頁裏面。若是超過了數據頁的一半,那麼可變長度列會選擇外部off-page存儲直到這行可以放入到數據頁的一半的空間裏,詳見Section 14.10.2, "File Space Management"。

 

  • Although InnoDB supports row sizes larger than 65,535 bytes internally, MySQL itself imposes a row-size limit of 65,535 for the combined size of all columns:
  • 雖然InnoDB內部支持的的行大小超過65,535 bytes,可是MySQL自身限制了全部行相加後的大小不能超過65,535:

 

mysql> CREATE TABLE t (a VARCHAR(8000), b VARCHAR(10000),

-> c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),

-> f VARCHAR(10000), g VARCHAR(10000)) ENGINE=InnoDB;

ERROR 1118 (42000): Row size too large. The maximum row size for the

used table type, not counting BLOBs, is 65535. You have to change some

columns to TEXT or BLOBs

 

See Section C.10.4, "Limits on Table Column Count and Row Size".

詳見Section C.10.4, "Limits on Table Column Count and Row Size".

 

  • On some older operating systems, files must be less than 2GB. This is not a limitation of InnoDB itself, but if you require a large tablespace, you will need to configure it using several smaller data files rather than one large data file.
  • 在一些老的操做系統上,文件必需要小於2GB。這不是InnoDB自己的限制,可是若是你須要一個大的表空間,那你就須要把表空間配製成使用多個小的數據文件,而不是一個大的文件。

 

  • The combined size of the InnoDB log files can be up to 512GB.
  • InnoDB全部的日誌文件相加最大能達到512GB。

 

  • The minimum tablespace size is slightly larger than 10MB. The maximum tablespace size is four billion database pages (64TB). This is also the maximum size for a table.
  • 最小的表空間大小比10MB多一點。最大的表空間大小是40億個數據頁(64TB)。這也是一個表的最大限制。

 

  • The default database page size in InnoDB is 16KB, or you can lower the page size to 8KB or 4KB by specifying the innodb_page_size option when creating the MySQL instance.
  • InnoDB裏默認的數據頁是16KB,或者在建立MySQL實例的時候經過innodb_page_size把數據頁減少到8KB or 4KB。

 

Note

 

Increasing the page size is not a supported operation: there is no guarantee that InnoDB will function normally with a page size greater than 16KB. Problems compiling or running InnoDB may occur. In particular, ROW_FORMAT=COMPRESSED in the Barracuda file format assumes that the page size is at most 16KB and uses 14-bit pointers.

是不能增長數據頁的大小的:InnoDB沒法保證可以處理超過16KB的數據頁。這樣在在編譯或者運行InnoDB的時候會發生錯誤。另外,Barracuda文件格式裏的ROW_FORMAT=COMPRESSED假設數據頁最可能是16KB,並使用了14-bit的指針。

 

A MySQL instance using a particular InnoDB page size cannot use data files or log files from an instance that uses a different page size. This limitation could affect restore or downgrade operations using data from MySQL 5.6, which does support page sizes other than 16KB.

同一個MySQL實例上不能把InnoDB的數據文件和日誌文件使用不一樣的大小的數據頁。這個限制會影響MySQL5.6的恢復和先下升級操做,由於它們不支持大於16KB的數據頁。

 

Index Types

 

  • InnoDB tables support FULLTEXT indexes, starting in MySQL 5.6.4. See Section 14.2.5.3, "InnoDB FULLTEXT Indexes" for details.
  • InnoDB表從MySQL5.6.4開始支持FULLTEXT索引。詳見14.2.5.3, "InnoDB FULLTEXT Indexes"。

 

  • InnoDB tables support spatial data types, but not indexes on them.
  • InnoDB支持空間數據類型,但上面沒法加索引。

 

Restrictions on InnoDB Tables

 

  • ANALYZE TABLE determines index cardinality (as displayed in the Cardinality column of SHOW INDEX output) by doing random dives to each of the index trees and updating index cardinality estimates accordingly. Because these are only estimates, repeated runs of ANALYZE TABLE could produce different numbers. This makes ANALYZE TABLE fast on InnoDB tables but not 100% accurate because it does not take all rows into account.
  • ANALYZE TABLE經過對每一個索引樹的進行random dives來確認索引的基數(顯示在SHOW INDEX 的Cardinality列上),並以此來更新索引的基數評估。由於這只是評估,因此重複運行ANALYZE TABLE可能會獲得不一樣的數字。這樣可以使得ANALYZE TABLE在InnoDB上運行得更快但沒法100%準確,由於它不會對全部的行進行統計。

 

You can make the statistics collected by ANALYZE TABLE more precise and more stable by turning on the innodb_stats_persistent configuration option, as explained in Section 14.4.11.1, "Configuring Persistent Optimizer Statistics Parameters". When that setting is enabled, it is important to run ANALYZE TABLE after major changes to indexed column data, because the statistics are not recalculated periodically (such as after a server restart) as they traditionally have been.

如Section 14.4.11.1, "Configuring Persistent Optimizer Statistics Parameters"所講述的,你能夠經過nnodb_stats_persistent配置參數使得ANALYZE TABLE獲得的結果更精確,更穩定。當開啓了這個參數的時候,那對在大的索引列數據改動以後運行ANALYZE TABLE是很是重要的,because the statistics are not recalculated periodically (such as after a server restart) as they traditionally have been.

 

You can change the number of random dives by modifying the innodb_stats_persistent_sample_pages system variable (if the persistent statistics setting is turned on), or the innodb_stats_transient_sample_pages system variable (if the persistent statistics setting is turned off).

你能夠經過修改innodb_stats_persistent_sample_pages系統變量來修改random dives的數量(要求開啓持久的統計信息),或者是innodb_stats_transient_sample_pages系統變量(關閉持久化統計信息的狀況下)。

 

MySQL uses index cardinality estimates only in join optimization. If some join is not optimized in the right way, you can try using ANALYZE TABLE. In the few cases that ANALYZE TABLE does not produce values good enough for your particular tables, you can use FORCE INDEX with your queries to force the use of a particular index, or set the max_seeks_for_key system variable to ensure that MySQL prefers index lookups over table scans. See Section 5.1.4, "Server System Variables", and Section B.5.5, "Optimizer-Related Issues".

MySQL只有在join優化的時候纔會使用索引基數的評估信息。若是一些join操做沒有以正確的方式進行優化,那麼你就須要運行ANALYZE TABLE。在少部分的狀況下ANALYZE TABLE沒法爲個別表生成足夠優質的數據,那麼你能夠在 查詢中使用FORCE INDEX來強制使用一個特定的索引,或者是設置max_seeks_for_key系統變量來確保MySQL更喜歡使用索引查找而不是表掃描。詳見Section 5.1.4, "Server System Variables"和Section B.5.5, "Optimizer-Related Issues"。

 

  • If statements or transactions are running on a table and ANALYZE TABLE is run on the same table followed by a second ANALYZE TABLE operation, the second ANALYZE TABLE operation is blocked until the statements or transactions are completed. This behavior occurs because ANALYZE TABLE marks the currently loaded table definition as obsolete when ANALYZE TABLE is finished running. New statements or transactions (including a second ANALYZE TABLE statement) must load the new table definition into the table cache, which cannot occur until currently running statements or transactions are completed and the old table definition is purged. Loading multiple concurrent table definitions is not supported.
  • 若是在一個表上運行一些語句或者事務,在同一個表上又接連着運行了兩次ANALYZE TABLE,那麼第二次ANALYZE TABLE操做會被阻塞直到語句或者事務運行完成。之因此這樣是由於ANALYZE TABLE在運行完成以後會把當前加載的數據標記爲過時。新的語句或者事務(包括第二次的運行的ANALYZE TABLE語句)必需要加載新的表定義到表緩存裏,這就要等待當前的運行的語句或者事務容許完成並把舊的表定義purge掉。同時加載多個表定義是不支持的。

 

  • SHOW TABLE STATUS does not give accurate statistics on InnoDB tables, except for the physical size reserved by the table. The row count is only a rough estimate used in SQL optimization.
  • SHOW TABLE STATUS不會給出精確的InnoDB統計信息,除非表預留了物理空間。行統計僅是用於SQL優化的大體評估。

 

  • InnoDB does not keep an internal count of rows in a table because concurrent transactions might "see" different numbers of rows at the same time. To process a SELECT COUNT(*) FROM t statement, InnoDB scans an index of the table, which takes some time if the index is not entirely in the buffer pool. If your table does not change often, using the MySQL query cache is a good solution. To get a fast count, you have to use a counter table you create yourself and let your application update it according to the inserts and deletes it does. If an approximate row count is sufficient, SHOW TABLE STATUS can be used.
  • InnoDB不會保留內部的行統計數據由於併發的事務在同一時間點上可能會看到不一樣的行統計數字。爲了處理SELECT COUNT(*) FROM t語句,InnoDB會掃密碼哦表上的索引,若是這個索引每一個徹底放置在buffer pool裏的話那就要花費一段的時間了。若是你的表不是常常更新的,那麼MySQL的query cache是個不錯的選擇。要快速地獲得這個統計值,你能夠本身建立一個表counter並讓應用程序在insert或者delete的時候去更新它。若是隻是要一個大概的值,那也可使用SHOW TABLE STATUS。

 

  • On Windows, InnoDB always stores database and table names internally in lowercase. To move databases in a binary format from Unix to Windows or from Windows to Unix, create all databases and tables using lowercase names.
  • 在Windows上,InnoDB在內部老是用小寫存儲數據和和表的名字。要在不一樣的區分大小的平臺上移動二進制格式的數據庫,數據庫和表名最好都用小寫。

 

  • An AUTO_INCREMENT column ai_col must be defined as part of an index such that it is possible to perform the equivalent of an indexed SELECT MAX(ai_col) lookup on the table to obtain the maximum column value. Typically, this is achieved by making the column the first column of some table index.
  • AUTO_INCREMENT列ai_col列必須定義成一個索引的一部分,這樣就能在表上執行等價的SELECT MAX(ai_col)索引查詢來獲得這列的最大值。一般,還要求這列是索引的第一個列(前綴列)。

 

  • InnoDB sets an exclusive lock on the end of the index associated with the AUTO_INCREMENT column while initializing a previously specified AUTO_INCREMENT column on a table.
  • InnoDB在初始化以前的AUTO_INCREMENT列的時候會在索引相關的AUTO_INCREMENT列的尾端放置一個排他鎖。

 

With innodb_autoinc_lock_mode=0, InnoDB uses a special AUTO-INC table lock mode where the lock is obtained and held to the end of the current SQL statement while accessing the auto-increment counter. Other clients cannot insert into the table while the AUTO-INC table lock is held. The same behavior occurs for "bulk inserts" with innodb_autoinc_lock_mode=1. Table-level AUTO-INC locks are not used with innodb_autoinc_lock_mode=2. For more information, See Section 14.6.5, "AUTO_INCREMENT Handling in InnoDB".

當innodb_autoinc_lock_mode=0,InnoDB會使用特殊的AUTO-INC表鎖模式,當要訪問auto-increment counter的時候,這個鎖會被得到並被保持到當前語句執行結束。當持有了AUTO-INC表鎖的時候其餘客戶端是沒法向表裏插入數據的。對於innodb_autoinc_lock_mode=1,"bulk inserts"也有相同的狀況。當innodb_autoinc_lock_mode=2的時候表界別的AUTO-INC鎖是沒法使用的。更多的信息查看Section 14.6.5, "AUTO_INCREMENT Handling in InnoDB"。

 

  • When you restart the MySQL server, InnoDB may reuse an old value that was generated for an AUTO_INCREMENT column but never stored (that is, a value that was generated during an old transaction that was rolled back).
  • 當你重啓MySQL服務的時候,InnoDB會重複利用AUTO_INCREMENT列生成但未存儲的舊值(也就是說是舊事務生成了但被回滾了的值)。

 

  • When an AUTO_INCREMENT integer column runs out of values, a subsequent INSERT operation returns a duplicate-key error. This is general MySQL behavior, similar to how MyISAM works.
  • 當AUTO_INCREMENT整數列的值超出了範圍,那就會報duplicate-key的錯誤,和MyISAM的狀況類似。

 

  • DELETE FROM tbl_name does not regenerate the table but instead deletes all rows, one by one.
  • DELETE FROM tbl_name不會再生表,而是一行一行地刪除全部行。

 

  • Cascaded foreign key actions do not activate triggers.
  • 級聯的外鍵動做不會觸發trigger。

 

  • You cannot create a table with a column name that matches the name of an internal InnoDB column (including DB_ROW_ID, DB_TRX_ID, DB_ROLL_PTR, and DB_MIX_ID). The server reports error 1005 and refers to error −1 in the error message. This restriction applies only to use of the names in uppercase.
  • 你不能用InnoDB的內部列(including DB_ROW_ID, DB_TRX_ID, DB_ROLL_PTR, and DB_MIX_ID)來爲列命名。這樣作的話會報1005的錯誤以及相關聯的−1錯誤。這種限制僅適用於名字使用的是大寫的字母。

 

Locking and Transactions

 

  • LOCK TABLES acquires two locks on each table if innodb_table_locks=1 (the default). In addition to a table lock on the MySQL layer, it also acquires an InnoDB table lock. Versions of MySQL before 4.1.2 did not acquire InnoDB table locks; the old behavior can be selected by setting innodb_table_locks=0. If no InnoDB table lock is acquired, LOCK TABLES completes even if some records of the tables are being locked by other transactions.
  • 當innodb_table_locks=1(默認)的時候LOCK TABLES會在每一個表上加兩個鎖。除了在MySQL層上的一個表鎖外,還會加一個InnoDB的表鎖。MySQL4.1.2以前的版本不會加InnoDB的表鎖;這種老的狀況和innodb_table_locks=0類似。若是沒有得到InnoDB的表鎖,即便表裏的部分數據被其餘的事務鎖住了,LOCK TABLES任然會執行完成的(不會阻塞)。

 

  • In MySQL 5.6, innodb_table_locks=0 has no effect for tables locked explicitly with LOCK TABLES ... WRITE. It does have an effect for tables locked for read or write by LOCK TABLES ... WRITE implicitly (for example, through triggers) or by LOCK TABLES ... READ.
  • 在MySQL5.6裏,innodb_table_locks=0不會影響對錶顯式地使用LOCK TABLES ... WRITE。可是對隱式(例如經過trigger)使用LOCK TABLES ...或者LOCK TABLES ... READ帶來的讀或寫鎖是有影響的。

 

  • All InnoDB locks held by a transaction are released when the transaction is committed or aborted. Thus, it does not make much sense to invoke LOCK TABLES on InnoDB tables in autocommit=1 mode because the acquired InnoDB table locks would be released immediately.
  • 一個事務持有的全部的鎖都會在它提交或者中斷的時候釋放。所以,在autocommit=1模式裏好像感受不到鎖的存在,由於持有的鎖都會被當即釋放掉。

 

  • You cannot lock additional tables in the middle of a transaction because LOCK TABLES performs an implicit COMMIT and UNLOCK TABLES.
  • 你不能在事務的中間去鎖額外的表,由於LOCK TABLES會隱式地執行COMMIT和UNLOCK TABLES。

 

  • The limit of 1023 concurrent data-modifying transactions has been raised in MySQL 5.5 and above. The limit is now 128 * 1023 concurrent transactions that generate undo records. You can remove any workarounds that require changing the proper structure of your transactions, such as committing more frequently.
  • 併發修改數據事務的限制1023在MySQL5.5級以後的版本已經有所提高。如今併發事務(生成undo記錄)的限制是128 * 1023。要避免這個限制你能夠更改你的事務結構,例如提交得更頻繁一些。
相關文章
相關標籤/搜索