1. 程式人生 > >MySql 大資料處理 效能提升 日誌清理

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