MySql社区版从5.7.11开始支持基于表的数据加密方案,模块名为keyring_file,支持加密整张表。这种是加密方式其实是基于文件加密的,一旦mysqld读取key启动后,将会解密整张表的数据,在mysql服务内,读取的数据都是解密后的,也就是说对客户端而言是无感知的。而这个key是本地存放的,mysql服务拥有读写这个key的权限。
针对已有的项目面对客户的安全审查需求,要对mysql进行表加密吗?
表加密影响性能吗?
对主从复制有没有影响?加密后对业务系统有影响吗?
对备份恢复有没有性能影像?
大数据量情况下,加密解密耗时吗?
加密后会增加存储空间占用吗?
数据库的有些特性通常都是双刃剑,有利也有弊,当然要测试过才知道。
以客户现场业务数据库数据量为基准,做如下测试:
1:增删改查加密前和加密后的性能对比
2:主从复制加密后系统主流程功能验证
3:加密前和加密后备份恢复时间对比
4:加密,解密耗时测试
5:加密前加密后占用存储空间对比
整个测试流程如下:
1.把现场数据拷回来,再进行还原到两台相同配置的服务器(8核16G内存),一台服务器所有表未加密,一台服务器所有表都加密;
2. 把现场业务系统的主要工作流的sql拿来,使用jmeter做并发性能测试对比;
3.设置主从,测试加密情况下,主从同步是否正常,同步是否及时;
考虑理论上应该没什么大问题,这里只简单的通过导入一个大批量插入数据的sql,来测试是否及时同步到从库。
4.在对第二台服务器中的所有业务数据表进行加密时,顺便记录加密耗时,以及加密后的空间占用计算空间增长,以及解密耗时;
5.分别测试加密和没有加密情况下的备份恢复时间。
经过两天的测试,基本结论如下:
1:表加密后业务系统的增删改查操作没有出现明显的性能降低
2:备份恢复的性能也没有明显的影响;
3:不影响主从复制,主从同步的及时性方面基本不受影响,没有出现明显的延迟;
4:空间增长方面,加密后反倒占用空间变小了;但是加密解密需较多的存储空间
由于数据库中设置了innodb_file_per_table=1,每个表独占一个表空间,分别单独加密。很明显的看到加密后的文件反倒比加密前变小了,估计是加密过程中去掉了文件中的碎片?
但是加密过程中需要有和原表文件大小差不多的空闲空间,否则加密会失败,解密也是一样。
因为mysql表加密采用AES加密算法,实际上源文件不变,Mysql会新生成一个临时文件,把原表文件的数据,不断读取写入到新文件,直到加密完成,再删除原文件,把加密后的文件替换到原文件。解密也是一样。
如果是单用户串行操作完成整个数据库的加密,可以简单的估算,加密解密额外需要的表空间大小为:需要加密的数据库中单个表文件占用空间最大的表,所占用的空间。
例如一个300G的数据库中,最大的表占用70G,如果是串行加密所有的表,整个加密所需要的额外的磁盘空间为70G。解密也是同样如此。
如果是多个会话并行执行加密操作,需要的空间就是各自需要加密的表中最大的表空间占用大小之和。
5:加密,解密非常耗时,在生产环境不可接受
如果上面说的空间占用情况还可以接受,可耗时问题就让人觉得mysql的加密非常鸡肋了。
测试下来,一个亿不到的业务量的情况下 整个系统的所有表加密完成时间需要整整一个晚上才行。
测试数据如下:测试环境,8G内存,4核CPU
表(行数) | 加密耗时 | 解密耗时 |
业务表1,字段不多(369928) | 24秒 |
3分56秒 |
业务表2,含有较多大文本字段(460436) | 4分35秒 | 25分34秒 |
业务表3(135185) | 8秒 |
11秒 |
业务表4,结构同表3,行数变多(21874128) | 15分56秒 |
13分48秒 |
业务表4(39948892) | 15分56秒 |
13分48秒 |
业务表5(95117965) | 1小时3分16秒 |
31分49秒 |
业务表6(2880473)) | 8分5秒 |
4分12秒 |
业务表7(95123072) | 2小时48分46秒 |
1小时40分 |
业务表8(490925) | 59秒 |
1分57秒 |
业务表9(411934) | 34秒 |
1分4秒 |
业务表10(95117965) | 6小时30分 |
超过6小时未完成 |
同样是9千多万的数据量,业务表10比表5字段少很多,只是多了一个varchar(500)类型的字段,存储文件的磁盘完整路径的。然而加密耗时却多了几倍。
6:在不停止业务系统的情况下,加密加密不会阻塞数据查询操作,但是会阻塞增删改操作。
根据执行时间直到加密解密操作完成才执行额外发起的增删改操作,成功或者超时,而对业务系统来说,多半都是会超时失败。
总结:
mysql的 加密解密虽然不需要停机操作,但是会阻塞对数据库的增删改操作。要想快速完成加密解密操作,最好是先停止业务系统读写数据库,再执行。
然而,加密解密的耗时决定了停机肯定会超出用户的能接受的停机时间!
再来看安全性方面,虽然数据库文件是加密的,但是只要能有mysql服务的账户,访问数据都是自动解密的,加密的意义又在哪里呢?而对于加密key来说,熟悉mysql加密原理的,完全可以把key一定带走。可以预见,社区版的加密的安全性方面只不过是掩耳盗铃罢了!
不知道大家的项目中是否也有数据库加密的需求呢?是否有别的更好的方式,在不购买企业版的情况下?