創建表的時候就會得到元數據。可以通過定義的方式對表的元數據進行生成
這個地方要注意的是
獨立表空間當中 ibd & frm分別存儲的是什么數據?
表空間:文件系統,為了更好的擴容數據庫的存儲空間
5.5以后的版本出現了共享表空間概念
表空間管理模式的出現是為了數據庫的存儲更容易擴展
5.6版本種默認的是獨立表空間
1、共享表空間:共享表空間用來存元數據和系統日志
show variables like '%path%';
innodb_data_file_path=ibdata1:12M:autoextend #默認只有1個共享表空間的文件 默認大小是12M 12M用完會自動增加
文件目錄下:/data 通過ls –lh查看
-rw-rw----. 1 mysql mysql 76M Aug 2 22:18 ibdata1
5.6種默認存儲什么?
系統數據、undo、臨時表
5.7中,會將undo和臨時表也都獨立出來
vim /etc/my.cnf
innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend --->錯誤的寫法
第一個50需要注意,需要與當前文件的ibdata1大小一致
[ERROR] InnoDB: Data file ./ibdata1 is of a different size 4864 pages (rounded down to MB) than
specified in the .cnf file 3200 pages!
參數應該更改為:
innodb_data_file_path=ibdata1:76M;ibdata2:50M:autoextend
一般企業會設置2個 512M或者2G
2、獨立表空間(5.6以后的默認模式):
對於用戶自主創建的表,會采用此種模式,每個表由一個獨立的表空間進行管理
-rw-rw---- 1 mysql mysql 8710 Jun 25 16:25 city.frm
-rw-rw---- 1 mysql mysql 671744 Jun 25 16:25 city.ibd
city.ibd就被稱之為獨立表空間的數據文件
city.frm就是元數據文件 就是創建表后生成的
獨立表空間可以通過開關控制 建議不要修改 一旦關閉就會存到共享表空間里去了
mysql> show variables like '%per_table%';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_file_per_table | ON |
+-----------------------+-------+
1 row in set (0.00 sec)
mysql>
alter table city discard tablespace;
alter table city import tablespace;
例子實踐:
這個案例主要就是當表只存在frm文件時,通過之前創建表的語句創造出ibd文件,再重新導入表空間,這樣就可以使用了
復制文件夾及文件夾下所有文件到對應文件夾
[root@db01 data]# cp -r db /data/3307/data/
第一個里程碑:在數據庫文件下進行文件備份 模擬刪除
[root@db01-sa world]# pwd
/application/mysql/data/world
[root@db01-sa world]# cp city.ibd city.ibd.bak
第二個里程碑:刪除表空間&查看表
mysql> alter table world.city discard tablespace;
Query OK, 0 rows affected (0.34 sec)
mysql> select * from world.city;
ERROR 1814 (HY000): Tablespace has been discarded for table 'city'
第三個里程碑:恢復ibd文件&將文件屬組給mysql
[root@db01-sa world]# cp city.ibd.bak city.ibd
[root@db01-sa world]# chown -R mysql.mysql city.ibd
第四個里程碑:重新賦予表空間
mysql> alter table world.city import tablespace;
Query OK, 0 rows affected, 1 warning (0.13 sec)
mysql> select * from city;
+------+---------------------+-------------+------------------------+------------+
| ID | Name | CountryCode | District | Population |
+------+---------------------+-------------+------------------------+------------+
| 1 | Kabul | AFG | Kabol | 1780000 |
| 2 | Qandahar | AFG | Qandahar | 237500 |
| 3 | Herat | AFG | Herat | 186800 |
| 4 | Mazar-e-Sharif | AFG | Balkh | 127800 |
| 5 | Amsterdam | NLD | Noord-Holland | 731200 |
| 6 | Rotterdam | NLD | Zuid-Holland | 593321 |
| 7 | Haag | NLD | Zuid-Holland | 440900 |
| 8 | Utrecht | NLD | Utrecht | 234323 |
補充:如果在物理層面直接刪除ibd文件會怎樣?
mysql> select * from city;
ERROR 1146 (42S02): Table 'world.city' doesn't exist
第一個里程碑:將ibd文件備份恢復& 修改文件屬組
[root@db01-sa world]# cp city.ibd.bak city.ibd
[root@db01-sa world]# chown -R mysql.mysql city.ibd
第二個里程碑:重啟數據庫
[root@db01-sa ~]# /etc/init.d/mysqld restart
第三個里程碑:查看表能否打開
mysql> select * from city;
+------+---------------------+-------------+------------------------+------------+
| ID | Name | CountryCode | District | Population |
+------+---------------------+-------------+------------------------+------------+
| 1 | Kabul | AFG | Kabol | 1780000 |
| 2 | Qandahar | AFG | Qandahar | 237500 |
| 3 | Herat | AFG | Herat | 186800 |
| 4 | Mazar-e-Sharif | AFG | Balkh | 127800 |
| 5 | Amsterdam | NLD | Noord-Holland | 731200 |
| 6 | Rotterdam | NLD | Zuid-Holland | 593321 |
備注:此次2個案例只在虛擬機上測試,最好是跨虛擬機再測試下
虛擬機上測試OK
truncate 作用一樣 類似於discard 表空間
七、老男孩Linux——MySQL學員案例
生產庫:
confulence庫 jira庫
聯想服務器(IBM)
磁盤500G 沒有raid
centos 6.8
mysql 5.6.33 innodb引擎 獨立表空間
編譯→制作rpm
/usr/bin/mysql
/var/lib/mysql
confulence jira
所有軟件和數據都在"/"
斷電了,啟動完成后“/” 只讀
fsck 重啟
結果:confulence庫 在 , jira庫不見了
求助:
這種情況怎么恢復?
我問:
有備份沒
求助:
連二進制日志都沒有,沒有備份,沒有主從
我說:
沒招了,jira需要硬盤恢復了。
求助:
1、jira問題拉倒中關村了
2、能不能暫時把confulence庫先打開用着
將生產庫confulence,拷貝到1:1虛擬機上/var/lib/mysql,直接訪問時訪問不了的
問:有沒有工具能直接讀取ibd
我說:我查查,最后發現沒有
我想出一個辦法來:
create table xxx
alter table confulence.t1 discard tablespace;
alter table confulence.t1 import tablespace;
虛擬機測試可行。
CREATE TABLE `city_new` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Name` char(35) NOT NULL DEFAULT '',
`CountryCode` char(3) NOT NULL DEFAULT '',
`District` char(20) NOT NULL DEFAULT '',
`Population` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`),
KEY `CountryCode` (`CountryCode`),
KEY `idx_popu` (`Population`)
) ENGINE=InnoDB AUTO_INCREMENT=4080 DEFAULT CHARSET=latin1;
面臨的問題,confulence庫中一共有107張表。
1、創建107和和原來一模一樣的表。
他有2016年的歷史庫,我讓他去他同時電腦上 mysqldump備份confulence庫
mysqldump -uroot -ppassw0rd -B confulence --no-data >test.sql
拿到你的測試庫,進行恢復
到這步為止,表結構有了。
2、表空間刪除。
select concat('alter table ',table_schema,'.'table_name,' discard tablespace;') from information_schema.tables where table_schema='confluence' into outfile '/tmp/discad.sql';
source /tmp/discard.sql
執行過程中發現,有20-30個表無法成功。主外鍵關系
ERROR 1215 (HY000): Cannot add foreign key constraint
很絕望,一個表一個表分析表結構,很痛苦。
set foreign_key_checks=0 跳過外鍵檢查。
把有問題的表表空間也刪掉了。
3、拷貝生產中confulence庫下的所有表的ibd文件拷貝到准備好的環境中
select concat('alter table ',table_schema,'.'table_name,' import tablespace;') from information_schema.tables where table_schema='confluence' into outfile '/tmp/discad.sql';
4、驗證數據
表都可以訪問了,數據挽回到了出現問題時刻的狀態(2-8)
案例模仿:
案例最新:
經過測試跨虛擬機也是可以成功的,如果需要foreign key的檢查用set忽略 先把表結構導進去再說;
#第一個里程碑:導出建表的語句
CREATE TABLE `city` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Name` char(35) NOT NULL DEFAULT '',
`CountryCode` char(3) NOT NULL DEFAULT '',
`District` char(20) NOT NULL DEFAULT '',
`Population` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`),
KEY `CountryCode` (`CountryCode`),
CONSTRAINT `city_ibfk_1` FOREIGN KEY (`CountryCode`) REFERENCES `country` (`Code`)
) ENGINE=InnoDB AUTO_INCREMENT=4080 DEFAULT CHARSET=latin1
#第二個里程碑:將表數據備份出來 防止萬一
[root@db01-sa world]# mysqldump -uroot -p123 world city >/server/scripts/backup_world_city.sql
#第三個里程碑:檢查查看備份語句是否正常
[root@db01-sa world]# cat /server/scripts/backup_world_city.sql
#第四個里程碑:
mysql> drop table world.city;
Query OK, 0 rows affected (0.05 sec)
mysql> show tables;
+-----------------+
| Tables_in_world |
+-----------------+
| country |
| countrylanguage |
| people |
| people_bak |
+-----------------+
4 rows in set (0.00 sec)
[root@db01-sa world]# ll
total 1248
-rw-r----- 1 root root 8710 Jun 26 23:11 city.frm.bak
-rw-r----- 1 root root 589824 Jun 26 22:49 city.ibd.bak
#第五個里程碑:
CREATE TABLE `city` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Name` char(35) NOT NULL DEFAULT '',
`CountryCode` char(3) NOT NULL DEFAULT '',
`District` char(20) NOT NULL DEFAULT '',
`Population` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`),
KEY `CountryCode` (`CountryCode`),
CONSTRAINT `city_ibfk_1` FOREIGN KEY (`CountryCode`) REFERENCES `country` (`Code`)
) ENGINE=InnoDB AUTO_INCREMENT=4080 DEFAULT CHARSET=latin1;
[root@db01-sa world]# \rm -fr city.ibd
[root@db01-sa world]# cp city.ibd.bak city.ibd
[root@db01-sa world]# chown -R mysql.mysql city.ibd
mysql> use world;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 1
Current database: world
+-----------------+
| Tables_in_world |
+-----------------+
| city |
| country |
| countrylanguage |
| people |
| people_bak |
+-----------------+
5 rows in set (0.01 sec)
mysql> select * from city;
ERROR 1146 (42S02): Table 'world.city' doesn't exist
mysql> alter table world.city import tablespace;#導入表空間
Query OK, 0 rows affected, 2 warnings (0.10 sec)
mysql> select * from city;
+------+---------------------+-------------+------------------------+------------+
| ID | Name | CountryCode | District | Population |
+------+---------------------+-------------+------------------------+------------+
| 1 | Kabul | AFG | Kabol | 1780000 |
| 2 | Qandahar | AFG | Qandahar | 237500 |
| 3 | Herat | AFG | Herat | 186800 |
| 4 | Mazar-e-Sharif | AFG | Balkh | 127800 |