OneSQL :: 开始对产品做减法,觉得从MySQL 8后要进入单存贮引挚方向

这段时间在思考MySQL的产品发展方向,觉得从MySQL 8将数据字典移入InnoDB开始,可以让MySQL逐步进入单存贮引挚的架构,将现在代码里的MyISAM、 Binlog、 Mrg_myisam、Paritition等引挚移除,只保留InnoDB。为方便更换存贮引挚,可以继续保持存贮引挚的API接口,但同一时间只支持单个存贮引挚,可以形成MySQL InnoDB、 MySQL TokuDB等版本。这样做的好处是明显的,可以解决复杂的Binlog问题(比如可以将逻辑日志放到存贮引挚日志中,再用异步线程解出逻辑日志,类似Oracle的Supplemental Log),也可以避免多引挚之间的XA问题,也许是非常值得整的一个发展方向。

想得太远了,OneSQL的并发控制机制,经过数个客户场景的验证后,觉得可以移除一些不必要的配置选项,简化一下以方便用户理解。准备从OneSQL 8开始,将参数从20多个减到9个,如下所示:

mysql> show variables like 'onesql_%';
+------------------------------------+-------+
| Variable_name                      | Value |
+------------------------------------+-------+
| onesql_autocommit_concurrency      | 16    |
| onesql_big_query_concurrency       | 12    |
| onesql_cpu_busy_count              | 3     |
| onesql_cpu_busy_offset             | 1     |
| onesql_login_restrict_mode         | 0     |
| onesql_query_concurrency           | 12    |
| onesql_sub_query_concurrency       | 4     |
| onesql_sub_transaction_concurrency | 3     |
| onesql_transaction_concurrency     | 48    |
+------------------------------------+-------+
9 rows in set (0.01 sec)

这样总体上就比较明确了,9个参数分成4个类型,分别是:

  • cpu绑定参数,可以指定MySQL用户进程能用的CPU Core,可指定从第几个CPU Core(cpu_busy_offset)开始,以及可以使用的Core数量(cpu_busy_count)。这两个参数可以动态调整,在客户端重新连接后资源绑定开始生效。
  • 运行模式控制,虽然MySQL 7增加了offline模式,但我们认为一个MySQL实例有三个状态(root only, root+replication, normal)比较好,可以更好的使用自动化脚本来进行主从切换,方便运行维护。
  • 多队列并发控制,可以分别限制四种不同操作的并发度,第一类操作为事务外的DML语句(autocommit concurrency),第二类为多语句事务(transaction concurrency),第三类为事务外简单的查询语句(query concurrency),第四类为事务外复杂的查询语句(big query concurrency)。可以根据应用的读写特证,设置不同的值,来优化读写相互干扰。
  • 秒杀队列并发控制,可以通过hint来传入记录标识,以控制同一条记录上的操作并发度,避免过多的会话到事务层去竞争同一条记录(查询操作sub query concurrency,更新操作sub transaction concurrency),可以极大地提升事务层的并发性能。可用来解决热点商品的高并发库存处理、热点账号的高并发记账业务等问题。

此外复用了存贮引挚层的“innodb_flush_log_at_trx_commit”参数,使其在设置为0时,进行实时异步刷日志(原先是1秒,不够及时),异步刷日志补丁有效地降低了InnoDB层锁的争用,降低了ut_delay函数占用的CPU资源。如果不使用秒杀队列并发控制功能,则对应用程序完全透明。从并发控制的效果上来讲(拆分了几个锁后,有效降低了spinlock的争用,降低了SYS CPU使用率),完全超越Thread Pool技术,但没有Thread Pool的使用限制问题,因为OneSQL的并发控制技术是在一对一的线程基础上进行优化的。

如果要使用秒杀队更并发控制功能,则需要更改热点场景下的SQL语句,选择性地添加如下hint,来进行事务优化:

  • auto_commit:如果语句成功,则同步执行事务提交指令,不再需要等待客户端发送commit指令,可以节约一个网络来回的锁持有时间。
  • auto_rollback:如果语句失败,则同步执行事务回滚指令,不再需要等待客户端发送rollback指令,可以节约一个网络来回的锁持有时间。
  • affect_rows:增加语句成功的记录数判断,除了语句本身没有错误外,还需要判断记录数来决定最终语句是否执行成功,可用于检查库存余额、账户余款必须大于0等要求。通常用来配合前面两个hint。
  • trx_queue:用来传递热点记录的标识,比如商品编号、账户号码等。

下面来看一下演示,这里会使用MySQL  5.7以后的hint方式,如下所示:

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> update /*+ auto_commit auto_rollback affect_rows(1) */ t_binlog
    ->   set col2 = col2 - 1 where id = 2;
Query OK, 1 row affected (0.22 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> update /*+ auto_commit auto_rollback affect_rows(1) */ t_binlog
    ->   set col2 = col2 - 1 where id in (2, 3);
ERROR 5000 (HY000): Affected rows does not match, require 1, real affected rows is 2.

需要使用热点队列的场景应当不多,因此SQL语句的更改量不会太大。即使不使用热点队列,设置好多队列并发控制的几个参数,也可以保障MySQL数据库的稳定运行了。还有没有办法让它更为简单?