MySql 大資料處理 效能提升 日誌清理
對於Oracle資料庫
truncate table後空間沒有釋放解決方法:
查詢資料庫表使用情況,發現一張無用的表,佔60G,查詢語句如下。
www.2cto.com
select segment_name,sum(bytes)/1024/1024/1024 from dba_segments
where owner='TEST' group by segment_name
order by 2 desc
truncate table後,再通過以上查詢空間沒有釋放,做以下操作就好了 :
alter table table_name enable row movement;
alter TABLE table_name shrink SPACE;
alter table table_name DISABLE row movement;
truncate表後,不釋放表空間
執行了truncate,但奇怪的是truncdate後這些表所佔的表空間並沒有釋放。
最後發現是INITIAL_EXTENT在作怪。
下面模擬一下問題的現象,及解決過程。
Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0
Connected as testtest
--1.T_IMP_TRUNCATE表中沒有資料。
SQL> select count(1) from T_IMP_TRUNCATE;
COUNT(1)
----------
0
--2.但T_IMP_TRUNCATE佔用了104MB的空間
SQL> SELECT SUM(T.BYTES) / 1024 / 1024 MB
2 FROM USER_SEGMENTS T
3 WHERE T.SEGMENT_NAME = 'T_IMP_TRUNCATE';
MB
----------
104
--3.truncate掉表T_IMP_TRUNCATE
SQL> truncate table T_IMP_TRUNCATE;
Table truncated
--4.分析表T_IMP_TRUNCATE
SQL> ANALYZE TABLE T_IMP_TRUNCATE COMPUTE STATISTICS;
Table analyzed
--5.發現表空間依然沒有釋放
SQL> SELECT SUM(T.BYTES) / 1024 / 1024 MB
2 FROM USER_SEGMENTS T
3 WHERE T.SEGMENT_NAME = 'T_IMP_TRUNCATE';
MB
----------
104
--6.檢查T_IMP_TRUNCATE表的INITIAL_EXTENT引數將近100MB
SQL> SELECT T.TABLE_NAME, T.INITIAL_EXTENT/1024/1024 mb
2 FROM USER_TABLES T
3 WHERE T.TABLE_NAME = 'T_IMP_TRUNCATE'
4 ;
TABLE_NAME MB
------------------------------ ----------
T_IMP_TRUNCATE 99.0
--7.決定對T_IMP_TRUNCATE表進行收縮shrink
--a.啟用行遷移
SQL> alter table T_IMP_TRUNCATE enable row movement;
--b.shrink表T_IMP_TRUNCATE
SQL> alter TABLE T_IMP_TRUNCATE shrink SPACE;
--c.關閉行遷移
SQL> alter table T_IMP_TRUNCATE DISABLE row movement;
Table altered
--8.shrink後T_IMP_TRUNCATE表空間已釋放
SQL> SELECT SUM(T.BYTES) / 1024 / 1024 MB
2 FROM USER_SEGMENTS T
3 WHERE T.SEGMENT_NAME = 'T_IMP_TRUNCATE';
MB
----------
0.1875
MySql的Delete、Truncate、Drop分析
相同點:
truncate 和不帶 where 子句的 delete,以及 drop 都會刪除表內的資料
不同點:
1. truncate 和 delete 只刪除資料不刪除表的結構(定義)
drop 語句將刪除表的結構被依賴的約束(constrain)、觸發器(trigger)、索引(index);依賴於該表的儲存過程/函式將保留,但是變為 invalid 狀態。
2. delete 語句是資料庫操作語言(dml),這操作會放到rollback segement 中,事務提交之後才生效;如果有相應的 trigger,執行的時候將被觸發。
truncate、drop 是資料庫定義語言(ddl),操作立即生效,原資料不放到 rollback segment 中,不能回滾,操作不觸發 trigger。
3. delete 語句不影響表所佔用的 extent,高水線(high watermark)保持原位置不動
顯然 drop 語句將表所佔用的空間全部釋放。
truncate 語句預設情況下見空間釋放到 minextents個 extent,除非使用reuse storage;truncate 會將高水線復位(回到最開始)。
4. 速度,一般來說: drop> truncate > delete
5. 安全性:小心使用 drop 和 truncate,尤其沒有備份的時候.否則哭都來不及
使用上,想刪除部分資料行用 delete,注意帶上where子句. 回滾段要足夠大.
想刪除表,當然用 drop
想保留表而將所有資料刪除,如果和事務無關,用truncate即可。如果和事務有關,或者想觸發trigger,還是用delete。
如果是整理表內部的碎片,可以用truncate跟上reuse stroage,再重新匯入/插入資料。
Delete from Tablename where 條件
Truncate table Tablename
Drop table Tablename
另:Mysql 的 truncate和delete的區別
truncate table table_name 和delete from table_name 都是刪除表中所有記錄。
區別:
truncate能夠快速清空一個表。並且重置auto_increment的值。而delete只能一行一行的刪除。
但對於不同的型別儲存引擎需要注意的地方是:
A 對於myisam
truncate會重置auto_increment的值為1。而delete後表仍然保持auto_increment。
B 對於innodb
truncate會重置auto_increment的值為1。delete後表仍然保持auto_increment。但是在做delete整個表之後重啟MySQL的話,則重啟後的auto_increment會被置為1。
也就是說,innodb的表本身是無法持久儲存auto_increment。delete表之後auto_increment仍然儲存在記憶體,但是重啟後就丟失了,只能從1開始。實質上重啟後的auto_increment會從 SELECT 1+MAX(ai_col) FROM t 開始。
MySQL刪除資料幾種情況以及是否釋放磁碟空間:
1、drop table table_name 立刻釋放磁碟空間 ,不管是 Innodb和MyISAM ;
2、truncate table table_name 立刻釋放磁碟空間 ,不管是 Innodb和MyISAM 。truncate table其實有點類似於drop table 然後creat,只不過這個create table 的過程做了優化,比如表結構檔案之前已經有了等等。所以速度上應該是接近drop table的速度;
3、delete from table_name刪除表的全部資料,對於MyISAM 會立刻釋放磁碟空間 (應該是做了特別處理,也比較合理),InnoDB 不會釋放磁碟空間;
4、對於delete from table_name where xxx帶條件的刪除, 不管是innodb還是MyISAM都不會釋放磁碟空間;
5、delete操作以後使用optimize table table_name 會立刻釋放磁碟空間。不管是innodb還是myisam 。所以要想達到釋放磁碟空間的目的,delete以後執行optimize table 操作。
6、delete from表以後雖然未釋放磁碟空間,但是下次插入資料的時候,仍然可以使用這部分空間。mysql truncate table未釋放表空間磁碟空間
truncate table tablename;
該命令可以清空一個表裡的所有資料,並歸1自增ID的值。
但myisam的表和innodb的表在使用上有一定的區別。
myisam表會清空所有資料,並釋放表空間,即硬碟空間會得到釋放。
innodb表也會清空所有資料,但不釋放表空間。
Innodb資料庫對於已經刪除的資料只是標記為刪除,並不真正釋放所佔用的磁碟空間,這就導致InnoDB資料庫檔案不斷增長。如果想徹底釋放這些已經刪除的資料,需要把資料庫匯出,刪除InnoDB資料庫檔案,然後再倒入。 下面是基本的步驟:
1 使用mysqldump命令將InnoDB資料庫匯出
2 停止MySQL
3 刪除所有InnoDB資料庫檔案和日誌
4 啟動MySQL並自動重建InnoDB資料庫檔案和日誌檔案
5 匯入前面備份的資料庫檔案
具體命令:
# 備份資料庫:
mysqldump -uroot -proot --quick --force --all-databases > mysqldump.sql
# 停止資料庫
service mysqld stop
# 刪除這些大檔案
rm /usr/local/mysql/var/ibdata1
rm /usr/local/mysql/var/ib_logfile*
# 手動刪除除Mysql之外所有資料庫資料夾,然後啟動資料庫
service mysqld start
# 還原資料
mysql -uroot -proot < mysqldump.sql
還有一種方式是在建立資料庫的時候設定innodb_file_per_table,這樣InnoDB會對每個表建立一個數據檔案,然後只需要執行OPTIMIZE TABLE 命令就可以釋放所有已經刪除的磁碟空間。
編輯my.ini或my.cnf 在innodb段中加入 innodb_file_per_table=1 # 1為啟用,0為禁用
通過mysql語句可以檢視該變數的值:mysql> show variables like '%per_table%';
Mysql InnoDB刪除資料後釋放磁碟空間的方法
這篇文章主要介紹了Mysql InnoDB刪除資料後釋放磁碟空間的方法,Innodb資料庫對於已經刪除的資料只是標記為刪除,並不真正釋放所佔用的磁碟空間,這就導致InnoDB資料庫檔案不斷增長,本文就講解釋放磁碟空間的方法,需要的朋友可以參考下Innodb資料庫對於已經刪除的資料只是標記為刪除,並不真正釋放所佔用的磁碟空間,這就導致InnoDB資料庫檔案不斷增長。
如果在建立資料庫的時候設定innodb_file_per_table=1,這樣InnoDB會對每個表建立一個數據檔案,然後只需要執行OPTIMIZE TABLE 命令就可以釋放所有已經刪除的磁碟空間。
執行OPTIMIZE TABLE 表名後,雖然最後會報Table does not support optimize, doing recreate + analyze instead,但其實已經成功了:)
-------------------------------------------------------------
如果沒有設定這個引數,又想釋放空間,徹底釋放這些已經刪除的資料,需要把資料庫匯出,刪除InnoDB資料庫檔案,然後再匯入。
下面是基本的步驟:
- 1 使用mysqldump命令將InnoDB資料庫匯出
- 2 停止MySQL
- 3 刪除所有InnoDB資料庫檔案和日誌
- 4 啟動MySQL並自動重建InnoDB資料庫檔案和日誌檔案
- 5 匯入前面備份的資料庫檔案
----------------------------------------------
具體命令:
# 備份資料庫:
mysqldump -uroot -proot --quick --force --all-databases > mysqldump.sql
# 停止資料庫
service mysqld stop
# 刪除這些大檔案
rm /usr/local/mysql/var/ibdata1
rm /usr/local/mysql/var/ib_logfile*
# 手動刪除除Mysql之外所有資料庫資料夾,然後啟動資料庫
service mysqld start
# 還原資料
mysql -uroot -proot < mysqldump.sql
實戰:
------備份DB
mysqldump -quick --database ixxx> ixxx.sql
------db所在的目錄情況
[[email protected] mysql]# ls -all
總計 64422864
drwxr-xr-x 3 mysql mysql 4096 09-08 23:21 .
drwxr-xr-x 4 root root 4096 06-02 22:08 ..
-rw-r----- 1 mysql mysql 64938311680 09-08 23:21 ibdata1
-rw-r----- 1 mysql mysql 268435456 09-08 23:21 ib_logfile0
-rw-r----- 1 mysql mysql 268435456 09-08 21:05 ib_logfile1
-rw-r----- 1 mysql mysql 268435456 09-08 23:18 ib_logfile2
-rw-rw---- 1 mysql mysql 403 09-08 23:21 localhost.localdomain.err
-rw-rw---- 1 mysql mysql 30362 09-08 19:41 localhost.localdomain.err-old
-rw-rw---- 1 mysql mysql 23292032 09-08 23:14 localhost-slow.log
drwx--x--x 2 mysql mysql 4096 05-19 01:50 mysql
-rw-rw---- 1 mysql mysql 137589360 09-08 23:21 mysql-bin.000001
-rw-rw---- 1 mysql mysql 19 09-08 19:42 mysql-bin.index
--------所有的db:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| ixxx |
| mysql |
+--------------------+
3 rows in set (0.00 sec)
-------刪除掉佔用空間的
drop database ixxx;
quit;
------停止mysql
[[email protected] mysql]# service mysql stop
Shutting down MySQL.. [確定]
------刪除innodb相關檔案
[[email protected] mysql]# ls -all
總計 64422864
drwxr-xr-x 3 mysql mysql 4096 09-08 23:21 .
drwxr-xr-x 4 root root 4096 06-02 22:08 ..
-rw-r----- 1 mysql mysql 64938311680 09-08 23:21 ibdata1
-rw-r----- 1 mysql mysql 268435456 09-08 23:21 ib_logfile0
-rw-r----- 1 mysql mysql 268435456 09-08 21:05 ib_logfile1
-rw-r----- 1 mysql mysql 268435456 09-08 23:18 ib_logfile2
-rw-rw---- 1 mysql mysql 403 09-08 23:21 localhost.localdomain.err
-rw-rw---- 1 mysql mysql 30362 09-08 19:41 localhost.localdomain.err-old
-rw-rw---- 1 mysql mysql 23292032 09-08 23:14 localhost-slow.log
drwx--x--x 2 mysql mysql 4096 05-19 01:50 mysql
-rw-rw---- 1 mysql mysql 137589360 09-08 23:21 mysql-bin.000001
-rw-rw---- 1 mysql mysql 19 09-08 19:42 mysql-bin.index
[[email protected] mysql]# rm -rf ibdata1
[[email protected] mysql]# rm -rf ib_logfile0
[[email protected] mysql]# rm -rf ib_logfile1
[[email protected] mysql]# rm -rf ib_logfile2
[[email protected] mysql]# ls -all
總計 157332
drwxr-xr-x 3 mysql mysql 4096 09-08 23:22 .
drwxr-xr-x 4 root root 4096 06-02 22:08 ..
-rw-rw---- 1 mysql mysql 403 09-08 23:21 localhost.localdomain.err
-rw-rw---- 1 mysql mysql 30362 09-08 19:41 localhost.localdomain.err-old
-rw-rw---- 1 mysql mysql 23292032 09-08 23:14 localhost-slow.log
drwx--x--x 2 mysql mysql 4096 05-19 01:50 mysql
-rw-rw---- 1 mysql mysql 137589360 09-08 23:21 mysql-bin.000001
-rw-rw---- 1 mysql mysql 19 09-08 19:42 mysql-bin.index
-----啟動mysql
[[email protected] mysql]# service mysql start
Starting MySQL.................... [確定]
此時檔案重新生成了:
[[email protected] mysql]# ls -all
總計 954808
drwxr-xr-x 3 mysql mysql 4096 09-08 23:23 .
drwxr-xr-x 4 root root 4096 06-02 22:08 ..
-rw-rw---- 1 mysql mysql 10485760 09-08 23:23 ibdata1
-rw-rw---- 1 mysql mysql 268435456 09-08 23:23 ib_logfile0
-rw-rw---- 1 mysql mysql 268435456 09-08 23:23 ib_logfile1
-rw-rw---- 1 mysql mysql 268435456 09-08 23:23 ib_logfile2
-rw-rw---- 1 mysql mysql 1912 09-08 23:23 localhost.localdomain.err
-rw-rw---- 1 mysql mysql 30362 09-08 19:41 localhost.localdomain.err-old
-rw-rw---- 1 mysql mysql 5 09-08 23:23 localhost.localdomain.pid
-rw-rw---- 1 mysql mysql 23292220 09-08 23:23 localhost-slow.log
drwx--x--x 2 mysql mysql 4096 05-19 01:50 mysql
-rw-rw---- 1 mysql mysql 137589360 09-08 23:21 mysql-bin.000001
-rw-rw---- 1 mysql mysql 106 09-08 23:23 mysql-bin.000002
-rw-rw---- 1 mysql mysql 38 09-08 23:23 mysql-bin.index
srwxrwxrwx 1 mysql mysql 0 09-08 23:23 mysql.sock
---進入查詢下mysql是否正常
[[email protected] mysql]# mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.1.45-community-log MySQL Community Server (GPL)
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
+--------------------+
2 rows in set (0.00 sec)
mysql> quit
Bye
--------建庫、重新匯入
CREATE DATABASE `ixxx` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
mysql ixxx<ixxx.sql
truncate操作後不釋放空間的解決辦法
truncate操作後不釋放空間的解決辦法
Truncate不支援回滾,並且不能truncate一個帶有外來鍵的表,如果要刪除首先要取消外來鍵,然後再刪除。
truncate table 後,有可能表空間仍沒有釋放,可以使用如下語句:
alter table 表名稱 deallocate UNUSED KEEP 0;
注意如果不加KEEP 0的話,表空間是不會釋放的。
例如:
alter table tablename deallocate UNUSED KEEP 0;
或者:
TRUNCATE TABLE tablename DROP STORAGE才能釋放表空間。
例如: truncate table tablename DROP STORAGE;
如何在刪除ibdata1和ib_logfile的情況下恢復MySQL資料庫
刪除了ibdata1和ib_logfile,後來,能正常啟動了,但所有的表通過show tables能看到,但是select的過程中卻報“Table doesn't exist”。
於是,建議他試試可傳輸表空間。
同時,自己也測試了下,確實可行。
測試版本 MySQL 5.6.32 社群版
恢復的基本步驟
1. 將原來的資料檔案COPY到其它目錄下。
2. 建立同名表,表結構必須保持一致。
3. 匯出表空間
mysql> ALTER TABLE t DISCARD TABLESPACE;
4. 將原來的資料檔案COPY回來
5. 匯入表空間
mysql> ALTER TABLE t IMPORT TABLESPACE
下面的演示會略為複雜,主要是還原整個場景,並針對上述步驟中的2,4做了一個測試。
首先,建立測試資料
在這裡建立兩張表。之所以建立兩張相同的表是為了方便後續的測試。
mysql> create table t1(id int,hiredate datetime); Query OK, 0 rows affected (0.14 sec) mysql> create table t2(id int,hiredate datetime); Query OK, 0 rows affected (0.01 sec) mysql> insert into t1 values(1,now()); Query OK, 1 row affected (0.06 sec) mysql> insert into t1 values(2,now()); Query OK, 1 row affected (0.00 sec) mysql> insert into t2 values(1,now()); Query OK, 1 row affected (0.00 sec) mysql> insert into t2 values(2,now()); Query OK, 1 row affected (0.00 sec)
關閉資料庫
# /usr/test/mysql-5.6.32-linux-glibc2.5-x86_64/bin/mysqladmin shutdown -uroot -p123456 -h127.0.0.1 -P3310
刪除ibdata1,ib_logfile0和ib_logfile1
[[email protected] data]# cd /data/ [[email protected] data]# ls auto.cnf ib_logfile0 localhost.localdomain.err mysql_upgrade_info test ibdata1 ib_logfile1 mysql performance_schema [[email protected] data]# rm -rf ibdata1 [[email protected] data]# rm -rf ib_logfile*[[email protected] data]# ls auto.cnf localhost.localdomain.err mysql mysql_upgrade_info performance_schema test
重新啟動資料庫
# /usr/test/mysql-5.6.32-linux-glibc2.5-x86_64/bin/mysqld --defaults-file=/usr/test/mysql-5.6.32-linux-glibc2.5-x86_64/my.cnf &
並沒有報錯
啟動過程中的日誌資訊如下:
# 2016-08-18 11:13:18 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details). 2016-08-18 11:13:18 0 [Note] /usr/test/mysql-5.6.32-linux-glibc2.5-x86_64/bin/mysqld (mysqld 5.6.32) starting as process 3948 ... 2016-08-18 11:13:18 3948 [Note] Plugin 'FEDERATED' is disabled. 2016-08-18 11:13:18 3948 [Note] InnoDB: Using atomics to ref count buffer pool pages 2016-08-18 11:13:18 3948 [Note] InnoDB: The InnoDB memory heap is disabled 2016-08-18 11:13:18 3948 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins 2016-08-18 11:13:18 3948 [Note] InnoDB: Memory barrier is not used 2016-08-18 11:13:18 3948 [Note] InnoDB: Compressed tables use zlib 1.2.3 2016-08-18 11:13:18 3948 [Note] InnoDB: Using Linux native AIO 2016-08-18 11:13:18 3948 [Note] InnoDB: Using CPU crc32 instructions 2016-08-18 11:13:18 3948 [Note] InnoDB: Initializing buffer pool, size = 128.0M 2016-08-18 11:13:19 3948 [Note] InnoDB: Completed initialization of buffer pool 2016-08-18 11:13:19 3948 [Note] InnoDB: The first specified data file ./ibdata1 did not exist: a new database to be created! 2016-08-18 11:13:19 3948 [Note] InnoDB: Setting file ./ibdata1 size to 12 MB 2016-08-18 11:13:19 3948 [Note] InnoDB: Database physically writes the file full: wait... 2016-08-18 11:13:19