本文是我最初于2017年底发表在我的个人微信公众号里面,现发布在这里。所以本文所列的tdsql的mysql/mariadb内核的功能和修复的bug,并没有包括我这2018年所完成的功能和修复的bug。我近期会写一篇文章总结一下我在2018年所完成的主要的tdsql数据库内核的功能和修复的bug。
在TDSQL-MariaDB-10.1.9和TDSQL-Percona中,有一些功能是官方发布的MariaDB/Percona 没有的。开发这些功能的目的是为TDSQL实现更好的安全性,性能,可靠性,可扩展性。它们可以配合TDSQL其他功能模块的功能,或者防止用户操作失误给自己带来损失。这些功能大多是在我们处理TDSQL的真实用户遇到的问题的过程中,总结经验后设计和实现的,因而具有很强的实用性。另外我还做了一些性能优化,使得TDSQL-MariaDB和TDSQL-Percona的性能均大幅超越了原版。
我在本文分如下几个方面介绍这些功能当中面向用户使用的功能。本文可以作为TDSQL内核的简明用户手册供应用开发者和DBA 查阅使用。
控制binlog写入量是为了
防止强同步超时 — binlog量过大会导致该事务之后的事务强同步等待超时,io线程没有机会接收后面的事务的binlog并发回ack
各种错误导致的事务执行错误,比如用户因为操作失误无条件删表的所有行之类
备机写入binlog量不受限制,防止主机上面放行的事务在备机上面被卡住。
系统安全机制
禁止直接访问mysqld服务器文件系统
为了保护TDSQL的用户免受黑客攻击,我们做了如下一些安全措施。
为了确保mysqld服务器文件系统的安全,对于tcp/ip登录 的用户,即使他有权限,也禁止如下操作:
1.禁止这样的用户通过以下SQL语句在mysqld运行的服务器上面创建或者打开文件:
a. select … into dump file
b. select … into outfile
c. load data infile …
在上面链接的脆弱性报告中,黑客正是通过 select into out file 来把其本地的攻击程序传输到服务器端的。
2.禁止这样的用户读写路径变量的值。路径变量就是其值是路径字符串的变量。这是为了防止客户端得知服务器的目录结构。黑客在得知目录结构后,更容易对用户发起数据窃取和攻击。
有了这些禁止措施,用户将无法通过TCP/IP连接的客户端在mysqld服务器上面创建或打开任意文件,用户创建的文件只有数据表文件等完全受mysqld掌控的文件。用户只能传输DDL/DML等SQL语句字符串以及得到它们的查询结果。
防止用户误删除和修改元数据
只允许unix socket 连上来的具有权限的用户删除 mysql, information/performance_schema, xa, sys, sysdb这几个系统DB以及其中的表,并且禁止这样的用户 alter/truncate 这些表,以及更新和删除这些表中的行。以便防止云上的用户因为误操作删除了这些重要的元数据库表。我们曾见过有用户误删除了mysql.user表,然后又试图挽回于是补创建了一个mysql.user表,结果新建的那个表的user 字段比标准的要短,于是后来创建用户失败了。有了这样的禁止以后,用户就不会给自己挖坑了。
阻止远程用户安装插件
MySQL提供了标准的接口允许用户实现自定义的功能,只要用户实现了这些接口就可以以动态库的形式挂载到mysqld进程中去执行用户的代码。这个机制虽然灵活方便,但是也是一个潜在的安全隐患。如果被攻击者利用的话,就可以在mysqld服务器上面以启动mysqld进程的linux用户的身份执行任意代码,是一个非常巨大的安全隐患。所以,TDSQL中,我们禁止通过TCP/IP连接上来的用户执行INSTALL PLUGIN语句安装插件。
阻止远程用户修改和读取安全开关变量
上述安全机制都有开关控制,但是远程用户无法修改和读取这些开关变量,TDSQL percona/mariadb会禁止这些行为,防止攻击者关掉上述安全措施。
其他防入坑机制
禁止用户设置产生 binlog_format=statement和 tx_isolation=read-committed 的组合。这个组合会导致insert语句失败。
允许用户不需要SUPER权限就可以修改session级别的 binlog_format,这样可以避免遇到上面情况,同时有时候用户不得不暂时修改binlog_format为statement,以便避免因为产生了海量的binlog导致无法执行DML语句,或者因为历史原因原有的某些数据表没有主键和唯一索引导致某些update/delete语句在备机上面执行太慢等问题。不过需要注意的是,当你set session binlog_format=statement后,TDSQL的强同步机制中非常重要的一个环节—闪回就无法正确工作了,因此必须尽快重新设置为row格式。
性能优化
线程池性能优化
我们对percona官方实现的线程池做了性能优化,实测明显提升了其TPS/QPS,并且缩短了平均响应时间。
组提交性能优化
Binlog事务组提交是一个开销较大的过程,在此过程中一个组的所有连接的工作线程中只有leader线程在工作,所有其他线程都需要等待leader线程完成工作。 这个组提交过程中我们发现了一些可以改进性能的点,通过优化改进了性能。
在TDSQL-MariaDB中,我们实现了TDSQL-Percona的一个性能优化 — 在engine prepare期间不刷engine 事务日志,而是在执行binlog写入之前,一次性flush engine事务日志。
强同步机制性能优化
TDSQL的强同步机制比mysql/mariadb官方实现的半同步机制更加高效,因为工作线程不需要阻塞等待备机应答,而是将会话脱离并放入等待队列然后继续处理其他连接上过来的新的请求。这样可以充分利用线程池中的线程,避免创建过多的线程。实测的性能提升(对比官方半同步机制)非常显著。
慢速删除
在TDSQL-Percona上面,当用户执行drop table或者alter table … drop partition 时,innodb不再立刻删除表空间文件,而是将这些文件重命名并且在后台逐步缩小这些文件并最终删除。这样做是为了避免一次性删除巨大的表空间文件给服务器的文件系统带来突增的IO负载,导致系统的TPS/QPS和响应时间出现波动。目前只支持innodb表的慢速删除。删除一个表后可以立刻创建同名表,也可以紧接着立刻删除这个同名表,不会发生名字冲突。如果用户执行drop database,那么不再慢速删除,而是立刻删除所有表。
同理,对于purge binary logs to命令也会做同样的慢速删除操作。