如何压缩Mysql数据库

如何压缩Mysql数据库,第1张

压缩表从名字上来看,简单理解为压缩后的表,也就是把原始表根据一定的压缩算法按照一定的压缩比率压缩后生成的表。

1.1 压缩能力强的产品

表压缩后从磁盘占用上看要比原始表要小很多。如果你熟悉列式数据,那对这个概念一定不陌生。比如,基于 PostgreSQL 的列式数据库 Greenplum;早期基于 MySQL 的列式数据库 inforbright;或者 Percona 的产品 tokudb 等,都是有压缩能力非常强的数据库产品。

1.2 为什么要用压缩表?

情景一:磁盘大小为 1T,不算其他的空间占用,只能存放 10 张 100G 大小的表。如果这些表以一定的比率压缩后,比如每张表从 100G 压缩到 10G,那同样的磁盘可以存放 100 张表,表的容量是原来的 10 倍。情景二:默认 MySQL 页大小 16K,而 OS 文件系统一般块大小为 4K,所以在 MySQL 在刷脏页的过程中,有一定的概率出现页没写全而导致数据坏掉的情形。比如 16K 的页写了 12K,剩下 4K 没写成功,导致 MySQL 页数据损坏。这个时候就算通过 Redo Log 也恢复不了,因为几乎有所有的关系数据库采用的 Redo Log 都记录了数据页的偏移量,此时就算通过 Redo Log 恢复后,数据也是错误的。所以 MySQL 在刷脏数据之前,会把这部分数据先写入共享表空间里的 DOUBLE WRITE BUFFER 区域来避免这种异常。此时如果 MySQL 采用压缩表,并且每张表页大小和磁盘块大小一致,比如也是 4K,那 DOUBLE WRITE BUFFER 就可以不需要,这部分开销就可以规避掉了。查看文件系统的块大小:

root@ytt-pc:/home/ytt#  tune2fs -l /dev/mapper/ytt--pc--vg-root  | grep -i 'block size'Block size:               4096

1.3 压缩表的优势

压缩表的优点非常明显,占用磁盘空间小!由于占用空间小,从磁盘置换到内存以及之后经过网络传输都非常节省资源。

简单来讲:节省磁盘 IO,减少网络 IO。

1.4 压缩表的缺陷

当然压缩表也有缺点,压缩表的写入(INSERT,UPDATE,DELETE)比普通表要消耗更多的 CPU 资源。

压缩表的写入涉及到解压数据,更新数据,再压缩数据,比普通表多了解压和再压缩两个步骤,压缩和解压缩需要消耗一定的 CPU 资源。所以需要选择一个比较优化的压缩算法。

1.5 MySQL 支持的压缩算法

这块是 MySQL 所有涉及到压缩的基础,不仅仅用于压缩表,也用于其它地方。比如客户端请求到 MySQL 服务端的数据压缩;主从之间的压缩传输;利用克隆插件来复制数据库 *** 作的压缩传输等等。

从下面结果可以看到 MySQL 支持的压缩算法为 zlib 和 zstd,MySQL 默认压缩算法为 zlib,当然你也可以选择非 zlib 算法,比如 zstd。至于哪种压缩算法最优,暂时没办法简单量化,依赖表中的数据分布或者业务请求。

通用规律只有使用 --all-databases (-A) 会 ERROR 1356,那就看看他到底备份了什么东西。于是喊上同事一起 less 看了下,上下扫了两眼。突然发现:1. 备份 SQL 文件里 DROP 掉了 mysql.proc;2. 后CREATE了一个新的 mysql.proc;3. LOCK TABLES 和 UNLOCK TABLES 中间居然没有备份 CREATE ROUTINE 任何数据?这不就是相当于每次导入全备都给我一个没有任何 sys schema routines 的全新 mysql.proc 表?那这不就异常的尴尬?

---- Table structure for table `proc`--

---- Dumping data for table `proc`-

真相大白在官方文档【sys-schema-usage】官方文档明确的告诉我们不会备份 sys 库。但在使用 mysqldump 在执行 --all-databases 会清空 mysql.proc 导致 sys 无法正常使用;这是一个 BUG,并且只存在于 MySQL 5.7.x !

1、mysql_upgrade install or upgrade sys schema

这个方案适用于 sys 库已经因为 mysqldump 导入而损坏的情况下使用。

注意:mysql_upgrade 在修理 sys 库的同时,还修理 mysql 库和用户库表(期间加锁且速度一般),有极小可能会误伤;使用 mysql_upgrade 的时候要加上 --upgrade-system-tables,不然会扫描用户库表。

2、全备时同时备份 sys 库

这个方案适用于需要还原的数据库,sys 库也不太正常的情况下使用;在全备后额外再备份一份 sys 库用于修复。

注意:不适用于做主从时使用它。

3、使用 databases 全备

这个方案适用于所有场景的全备需求,100% 安全。

4、使用 mysql-sys 开源代码

如果你的数据库 sys 全部中招了,又是生产库。那你只能用这个方法;

mysql-sys:https://github.com/mysql/mysql-sys

中记录了 sys 库的创建语句将文件下载到本地,然后根据数据库版本,执行以下命令即可。

一、mysqldump 备份的时候使用 --extended-insert=false 参数。

原理如下:

使用MySqldump命令导出数据时的注意

在使用Mysql做基础数据库时,由于需要将库B的数据导入库A,而A,B库又包含大量相同的数据,需要使用mysqldump导出脚本.

通常的命令会是

?

1

2

mysqldump -t 'dbName' >'scriptName.sql'

mysql -f 'dbName' <'scriptName.sql'

而使用如下命令导入到A库时不会成功,现象是报出几个Duplicate key error后就完毕了,并未将其余正确的数据插入到A库中.

捣鼓了好一会,发现在使用mysqldump导出的脚本命令中,insert语句采用是multiline insert synax.而不是采用single insert synax.原来是这个问题. 多行的插入语法在第一个主健重复错误后就不执行后续的对应表的插入语句了.

于是再加参数 --extended-insert=false,完整的命令是

?

1

mysqldump --extended-insert=false dbname >scriptname.sql

二、手工把表中username里存在重复的值删除

使用数据库工具 Navicat 之类的,执行查询:

?

1

Select username,Count(*) From cdb_members Group By username Having Count(*) >1

结果中就能显示出表中存在重复的字段, 你会看到2个或者多个完全一模一样重复的用户名。删除其中一行的记录,保存后再导出数据库。

这里需要特别注意:备份的时候,把表结构跟数据分开!

以下是 mysqldump 的一些使用参数

备份数据库:

?

1

2

3

#mysqldump 数据库名 >数据库备份名

#mysqldump -A -u用户名 -p密码 数据库名>数据库备份名

#mysqldump -d -A --add-drop-table -uroot -p >xxx.sql

1.导出结构不导出数据

?

1

mysqldump -d 数据库名 -uroot -p >xxx.sql

2.导出数据不导出结构

?

1

mysqldump -t 数据库名 -uroot -p >xxx.sql

3.导出数据和表结构

?

1

mysqldump 数据库名 -uroot -p >xxx.sql

4.导出特定表的结构

?

1

2

mysqldump -uroot -p -B数据库名 --table 表名 >xxx.sql

#mysqldump [OPTIONS] database [tables]

mysqldump支持下列选项:

--add-locks

在每个表导出之前增加LOCK TABLES并且之后UNLOCK TABLE。(为了使得更快地插入到MySQL)。

--add-drop-table

在每个create语句之前增加一个drop table。

--allow-keywords

允许创建是关键词的列名字。这由表名前缀于每个列名做到。

-c, --complete-insert

使用完整的insert语句(用列名字)。

-C, --compress

如果客户和服务器均支持压缩,压缩两者间所有的信息。

--delayed

用INSERT DELAYED命令插入行。

-e, --extended-insert

使用全新多行INSERT语法。(给出更紧缩并且更快的插入语句)

-#, --debug[=option_string]

跟踪程序的使用(为了调试)。

--help

显示一条帮助消息并且退出。

--fields-terminated-by=...

 

--fields-enclosed-by=...

 

--fields-optionally-enclosed-by=...

 

--fields-escaped-by=...

 

--fields-terminated-by=...

这些选择与-T选择一起使用,并且有相应的LOAD DATA INFILE子句相同的含义。

LOAD DATA INFILE语法。

-F, --flush-logs

在开始导出前,洗掉在MySQL服务器中的日志文件。

-f, --force,

即使我们在一个表导出期间得到一个SQL错误,继续。

-h, --host=..

从命名的主机上的MySQL服务器导出数据。缺省主机是localhost。

-l, --lock-tables.

为开始导出锁定所有表。

-t, --no-create-info

不写入表创建信息(CREATE TABLE语句)

-d, --no-data

不写入表的任何行信息。如果你只想得到一个表的结构的导出,这是很有用的!

--opt

同--quick --add-drop-table --add-locks --extended-insert --lock-tables。

应该给你为读入一个MySQL服务器的尽可能最快的导出。

-pyour_pass, --password[=your_pass]

与服务器连接时使用的口令。如果你不指定“=your_pass”部分,mysqldump需要来自终端的口令。

-P port_num, --port=port_num

与一台主机连接时使用的TCP/IP端口号。(这用于连接到localhost以外的主机,因为它使用 Unix套接字。)

-q, --quick

不缓冲查询,直接导出至stdout;使用mysql_use_result()做它。

-S /path/to/socket, --socket=/path/to/socket

与localhost连接时(它是缺省主机)使用的套接字文件。

-T, --tab=path-to-some-directory

对于每个给定的表,创建一个table_name.sql文件,它包含SQL CREATE 命令,和一个table_name.txt文件,它包含数据。 注意:这只有在mysqldump运行在mysqld守护进程运行的同一台机器上的时候才工作。.txt文件的格式根据--fields-xxx和--lines--xxx选项来定。

-u user_name, --user=user_name

与服务器连接时,MySQL使用的用户名。缺省值是你的Unix登录名。

-O var=option, --set-variable var=option设置一个变量的值。可能的变量被列在下面。

-v, --verbose

冗长模式。打印出程序所做的更多的信息。

-V, --version

打印版本信息并且退出。

-w, --where='where-condition'

只导出被选择了的记录;注意引号是强制的!

"--where=user='jimf'" "-wuserid>1" "-wuserid<1"

导入数据:

由于mysqldump导出的是完整的SQL语句,所以用mysql客户程序很容易就能把数据导入了:

?

#mysql 数据库名 <文件名

#source /tmp/xxx.sql


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/8734829.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-20
下一篇 2023-04-20

发表评论

登录后才能评论

评论列表(0条)

保存