插件式存儲引擎是 MySQL 數據庫最重要的特性之一,用戶能夠根據應用的須要選擇如何存儲和索引數據、是否使用事務等。MySQL 默認支持多種存儲引擎,以適用於不一樣領域的數據庫應用須要,用戶能夠經過選擇使用不一樣的存儲引擎提升應用的效率,提供靈活的存儲,用戶甚至能夠按照本身的須要定製和使用本身的存儲引擎,以實現最大程度的可定製性。mysql
MySQL 5.0 支持的存儲引擎包括 MyISAM、InnoDB、BDB、MEMORY、MERGE、EXAMPLE、NDB Cluster、ARCHIVE、CSV、BLACKHOLE、FEDERATED 等,其中 InnoDB 和 BDB 提供事務安全表,其餘存儲引擎都是非事務安全表。sql
建立新表時若是不指定存儲引擎,那麼系統就會使用默認存儲引擎,MySQL 5.5 以前的默認存儲引擎是 MyISAM,5.5 以後改成了 InnoDB。數據庫
經常使用存儲引擎對比緩存
特色 | MyISAM | InnoDB | MEMORY | MERGE | NDB |
---|---|---|---|---|---|
存儲限制 | 有 | 64 TB | 有 | 沒有 | 有 |
事物安全 | 支持 | ||||
鎖機制 | 表鎖 | 行鎖 | 表鎖 | 表鎖 | 行鎖 |
B 樹索引 | 支持 | 支持 | 支持 | 支持 | 支持 |
哈希索引 | 支持 | 支持 | |||
全文索引 | 支持 | ||||
集羣索引 | 支持 | ||||
數據緩存 | 支持 | 支持 | 支持 | ||
索引緩存 | 支持 | 支持 | 支持 | 支持 | 支持 |
數據可壓縮 | 支持 | ||||
空間使用 | 低 | 高 | N/A | 低 | 低 |
內存使用 | 低 | 高 | 中等 | 低 | 高 |
批量插入的速度 | 高 | 低 | 高 | 高 | 高 |
支持外鍵 | 支持 |
1)查詢當前數據庫支持的存儲引擎安全
> show engines; +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ | Engine | Support | Comment | Transactions | XA | Savepoints | +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ | ARCHIVE | YES | Archive storage engine | NO | NO | NO | | BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO | | MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO | | FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL | | MyISAM | YES | MyISAM storage engine | NO | NO | NO | | PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO | | InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES | | MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO | | CSV | YES | CSV storage engine | NO | NO | NO | +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ 9 rows in set (0.00 sec)
> show variables like 'have%'; +------------------------+----------+ | Variable_name | Value | +------------------------+----------+ | have_compress | YES | | have_dynamic_loading | YES | | have_geometry | YES | | have_openssl | YES | | have_profiling | YES | | have_query_cache | NO | | have_rtree_keys | YES | | have_ssl | YES | | have_statement_timeout | YES | | have_symlink | DISABLED | +------------------------+----------+ 10 rows in set (0.00 sec)
2)查看當前默認存儲引擎併發
> show variables like 'table_type'; +---------------+--------+ | Variable_name | Value | +---------------+--------+ | table_type | InnoDB | +---------------+--------+ 1 row in set (0.00 sec)
3)設置新建表的存儲引擎app
# create table 表名 ( 列名稱字段 數據類型(長度) 約束條件, 列名稱字段 數據類型(長度) 約束條件 ) engine = 存儲引擎名; > create table ai ( i bigint(20) not null auto_increment, primary key(i) ) engine = MyISAM; Query OK, 0 rows affected (0.08 sec)
4)修改已有表的存儲引擎ide
# 修改已有表的存儲引擎 # alter table 表名 engine = 存儲引擎名; > alter table ai engine = InnoDB; Query OK, 0 rows affected (0.09 sec) Records: 0 Duplicates: 0 Warnings: 0
5)顯示錶的存儲引擎工具
# 顯示錶的存儲引擎 # show create table 表名; > show create table ai; +-------+-----------------------------------------------------------------------------------------+ | Table | Create Table | +-------+-----------------------------------------------------------------------------------------+ | ai | CREATE TABLE `ai` ( `i` bigint(20) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`i`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci | +-------+-----------------------------------------------------------------------------------------+ 1 row in set (0.01 sec)
MyISAM 是 MySQL 默認的存儲引擎。MyISAM 不支持事務、也不支持外鍵,其優點是訪問的速度快,對事務完整性沒有要求或者以 SELECT、INSERT 爲主的應用基本上均可以使用這個引擎來建立表。性能
若是應用是以讀操做和插入操做爲主,只有不多的更新和刪除操做,而且對事務的完整性、併發性要求不是很高,那麼選擇這個存儲引擎是很是適合的。MyISAM 是在 Web、數據倉儲和其餘應用環境下最常使用的存儲引擎之一。
每一個 MyISAM 在磁盤上存儲成 3 個文件,其文件名都和表名相同,但擴展名分別是:
數據文件和索引文件能夠放置在不一樣的目錄,平均分佈 IO,得到更快的速度。
要指定索引文件和數據文件的路徑,須要在建立表的時候經過 DATA DIRECTORY 和 INDEX DIRECTORY 語句指定,也就是說不一樣 MyISAM 表的索引文件和數據文件能夠放置到不一樣的路徑下。文件路徑須要是絕對路徑,而且具備訪問權限。
MyISAM 類型的表可能會損壞,緣由多是多種多樣的,損壞後的表可能不能被訪問,會提示須要修復或者訪問後返回錯誤的結果。
MyISAM 類型的表提供修復的工具,能夠用 CHECK TABLE 語句來檢查 MyISAM 表的健康,並用 REPAIR TABLE 語句修復一個損壞的 MyISAM 表。
表損壞可能致使數據庫異常從新啓動,須要儘快修復並儘量地確認損壞的緣由。
MyISAM 的表還支持 3 種不一樣的存儲格式,分別是:
其中,靜態表是默認的存儲格式。靜態表中的字段都是非變長字段,這樣每一個記錄都是固定長度的,這種存儲方式的優勢是存儲很是迅速,容易緩存,出現故障容易恢復;缺點是佔用的空間一般比動態表多。靜態表的數據在存儲時會按照列的寬度定義補足空格,可是在應用訪問的時候並不會獲得這些空格,這些空格在返回給應用以前已經去掉。
動態表中包含變長字段,記錄不是固定長度的,這樣存儲的優勢是佔用的空間相對較少,可是頻繁地更新和刪除記錄會產生碎片,須要按期執行 OPTIMIZE TABLE 語句或 myisamchk-r 命令來改善性能,而且在出現故障時恢復相對比較困難。
壓縮表由 myisampack 工具建立,佔據很是小的磁盤空間。由於每一個記錄是被單獨壓縮的,因此只有很是小的訪問開支。
InnoDB 存儲引擎提供了具備提交、回滾和崩潰恢復能力的事務安全。可是對比 MyISAM 的存儲引擎,InnoDB 寫的處理效率差一些,而且會佔用更多的磁盤空間以保留數據和索引。
用於事務處理應用程序,支持外鍵。若是應用對事務的完整性有比較高的要求,在併發條件下要求數據的一致性,數據操做除了插入和查詢之外,還包括不少的更新、刪除操做,那麼 InnoDB 存儲引擎應該是比較合適的選擇。InnoDB 存儲引擎除了有效地下降因爲刪除和更新致使的鎖定,還能夠確保事務的完整提交(Commit)和回滾(Rollback),對於相似計費系統或者財務系統等對數據準確性要求比較高的系統,InnoDB 都是合適的選擇。
1)InnoDB 表的自動增加列能夠手工插入,可是插入的值若是是空或者 0,則實際插入的將是自動增加後的值。
> create table autoincre_demo ( i smallint not null auto_increment, name varchar(10), primary key(i) ) engine = innodb; Query OK, 0 rows affected (0.04 sec) > insert into autoincre_demo values (1, '1'), (0, '2'), (null, '3'); Query OK, 3 rows affected (0.09 sec) Records: 3 Duplicates: 0 Warnings: 0 > select * from autoincre_demo; +---+------+ | i | name | +---+------+ | 1 | 1 | | 2 | 2 | | 3 | 3 | +---+------+ 3 rows in set (0.00 sec)
2)能夠經過 alter table *** auto_increment = n;
語句強制設置自動增加列的初始值。
3)可使用 last_insert_id()
查詢當前線程最後插入記錄使用的值。若是一次插入了多條記錄,那麼返回的是第一條記錄使用的自動增加值。
> insert into autoincre_demo values(4, '4'); Query OK, 1 row affected (0.05 sec) > select last_insert_id(); +------------------+ | last_insert_id() | +------------------+ | 2 | +------------------+ 1 row in set (0.01 sec) > insert into autoincre_demo (name) values ('5'), ('6'), ('7'); Query OK, 3 rows affected (0.01 sec) Records: 3 Duplicates: 0 Warnings: 0 > select last_insert_id(); +------------------+ | last_insert_id() | +------------------+ | 5 | +------------------+ 1 row in set (0.00 sec)
4)對於 InnoDB 表,自動增加列必須是索引。若是是組合索引,也必須是組合索引的第一列,可是對於 MyISAM 表,自動增加列能夠是組合索引的其餘列,這樣插入記錄後,自動增加列是按照組合索引的前面幾列進行排序後遞增的。
> create table autoincre_demo ( d1 smallint not null auto_increment, d2 smallint not null, name varchar(10), index(d2, d1) ) engine = myisam; Query OK, 0 rows affected (0.07 sec) > insert into autoincre_demo (d2, name) values (2, '2'), (3, '3'), (4, '4'), (2, '2'), (3, '3'), (4, '4'); Query OK, 6 rows affected (0.01 sec) Records: 6 Duplicates: 0 Warnings: 0 > select * from autoincre_demo; +----+----+------+ | d1 | d2 | name | +----+----+------+ | 1 | 2 | 2 | | 1 | 3 | 3 | | 1 | 4 | 4 | | 2 | 2 | 2 | | 2 | 3 | 3 | | 2 | 4 | 4 | +----+----+------+ 6 rows in set (0.00 sec)
autoincre_demo
,自動增加列 d1 做爲組合索引的第二列,對該表插入一些記錄後,能夠發現自動增加列是按照組合索引的第一列 d2 進行排序後遞增的。1)MySQL 支持外鍵的存儲引擎只有 InnoDB,在建立外鍵的時候,要求父表必須有對應的索引,子表在建立外鍵的時候也會自動建立對應的索引。
> create table country ( country_id smallint unsigned not null auto_increment, country varchar(50) not null, last_update timestamp not null default current_timestamp on update current_timestamp, primary key (country_id) ) engine = InnoDB default charset = utf8; Query OK, 0 rows affected, 1 warning (0.05 sec) > create table city ( city_id smallint unsigned not null auto_increment, city varchar(50) not null, country_id smallint unsigned not null, last_update timestamp not null default current_timestamp on update current_timestamp, primary key(city_id), key idx_fk_country_id(country_id), # constraint 約束名稱 foreign key(外鍵名稱) references 源表(主鍵名稱) constraint fk_city_country foreign key(country_id) references country(country_id) on delete restrict on update cascade ) engine = InnoDB default charset = utf8; Query OK, 0 rows affected, 1 warning (0.07 sec)
2)在建立索引時,能夠指定在刪除、更新父表時,對子表進行的相應操做,包括 restrict、cascade、set null 和 no action。選擇後兩種方式的時候要謹慎,可能會由於錯誤的操做致使數據的丟失。
> select * from country where country_id = 1; +------------+-------------+---------------------+ | country_id | country | last_update | +------------+-------------+---------------------+ | 1 | Afghanistan | 2006-02-15 04:44:00 | +------------+-------------+---------------------+ 1 row in set (0.00 sec) > select * from city where country_id = 1; +---------+-------+------------+---------------------+ | city_id | city | country_id | last_update | +---------+-------+------------+---------------------+ | 251 | Kabul | 1 | 2006-02-15 04:45:25 | +---------+-------+------------+---------------------+ 1 row in set (0.00 sec) > delete from country where country_id=1; ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails ('sakila/city', CONSTRAINT 'fk_city_country' FOREIGN KEY ('country_id') REFERENCES 'country' ('country_id') ON UPDATE CASCADE) > update country set country_id = 10000 where country_id = 1; Query OK, 1 row affected (0.04 sec) Rows matched: 1 Changed: 1 Warnings: 0 > select * from country where country = 'Afghanistan'; +------------+-------------+---------------------+ | country_id | country | last_update | +------------+-------------+---------------------+ | 10000 | Afghanistan | 2007-07-17 09:45:23 | +------------+-------------+---------------------+ 1 row in set (0.00 sec) > select * from city where city_id = 251; +---------+-------+------------+---------------------+ | city_id | city | country_id | last_update | +---------+-------+------------+---------------------+ | 251 | Kabul | 10000 | 2006-02-15 04:45:25 | +---------+-------+------------+---------------------+ 1 row in set (0.00 sec)
3)在導入多個表的數據時,若是須要忽略表以前的導入順序,能夠暫時關閉外鍵的檢查;一樣,在執行 load data 和 alter table 操做的時候,能夠經過暫時關閉外鍵約束來加快處理的速度,關閉的命令是 set foreign_key_checks = 0;
,執行完成以後,經過執行 set foreign_key_checks = 1;
語句改回原狀態。
4)對於 InnoDB 類型的表,外鍵的信息經過使用 show create table 或者 show table status 命令均可以顯示。
# show create table 表名; > show create table city; +-------+--------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+--------------------------------------------------------------------------------------------------------------------------------------+ | city | CREATE TABLE `city` ( `city_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, `city` varchar(50) NOT NULL, `country_id` smallint(5) unsigned NOT NULL, `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`city_id`), KEY `idx_fk_country_id` (`country_id`), CONSTRAINT `fk_city_country` FOREIGN KEY (`country_id`) REFERENCES `country` (`country_id`) ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | +-------+--------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) # show table status like 表名; > show table status like 'city'; +------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+ | Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | +------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+ | city | InnoDB | 10 | Dynamic | 0 | 0 | 16384 | 0 | 16384 | 0 | 1 | +------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+ ---------------------+-------------+------------+-----------------+----------+----------------+---------+ Create_time | Update_time | Check_time | Collation | Checksum | Create_options | Comment | ---------------------+-------------+------------+-----------------+----------+----------------+---------+ 2018-06-21 18:58:55 | NULL | NULL | utf8_general_ci | NULL | | | ---------------------+-------------+------------+-----------------+----------+----------------+---------+ 1 row in set (0.06 sec)
InnoDB 存儲表和索引有如下兩種方式。
innodb_data_home_dir
和 innodb_data_file_path
定義的表空間中,能夠是多個文件。要使用多表空間的存儲方式,須要設置參數 innodb_file_per_table
,而且從新啓動服務後才能夠生效,對於新建的表按照多表空間的方式建立,已有的表仍然使用共享表空間存儲。若是將已有的多表空間方式修改回共享表空間的方式,則新建表會在共享表空間中建立,但已有的多表空間的表仍然保存原來的訪問方式。因此多表空間的參數生效後,只對新建的表生效。
多表空間的數據文件沒有大小限制,不須要設置初始大小,也不須要設置文件的最大限制、擴展大小等參數。
對於使用多表空間特性的表,能夠比較方便地進行單表備份和恢復操做,可是直接複製 .ibd 文件是不行的,由於沒有共享表空間的數據字典信息,直接複製的 .ibd 文件和 .frm 文件恢復時是不能被正確識別的,但能夠經過如下命令將備份恢復到數據庫中,可是這樣的單表備份,只能恢復到表原來所在的數據庫中,而不能恢復到其餘的數據庫中。若是要將單表恢復到目標數據庫,則須要經過 mysqldump 和 mysqlimport 來實現。
alter table tbl_name discard tablespace; alter table tbl_name import tablespace;
即使在多表空間的存儲方式下,共享表空間仍然是必須的,InnoDB 把內部數據詞典和在線重作日誌放在這個文件中。