MySQL5.7 与 MariaDB10.1 审计插件兼容性验证
这是一篇关于发现 MariaDB 审计插件导致 MySQL 发生 crash 后,展开适配验证并进行故障处理的文章。
作者:官永强
爱可生DBA 团队成员,擅长 MySQL 运维方面的技能。热爱学习新知识,亦是个爱打游戏的宅男。
本文来源:原创投稿
- 爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
背景
在使用 CentOS Linux release 7.5.1804 (Core) 虚机为 MySQL5.7.34 安装 MariaDB 审计插件时发现:当使用通过解压 mariadb-10.1.48-linux-glibc_ 214-x86_64.tar.gz 获得的 server_audit.so
时,MySQL 会出现 Crash 的情况,通过手动重启 MySQL 也会马上发生 Crash。由此不禁思考:
- 其他版本的审计插件对该版本MySQL是否也有兼容性问题?
- 其他版本的MySQL是否也无法使用该版本的审计插件?
- 对于这样的情况是否有合适的解决方法?
通过查阅官网信息获得 MySQL 5.7 与 MariaDB 10.1 版本审计插件是适配的,于是这里选择了 MySQL 5.7 的部分版本与 MariaDB 10.1 的部分版本进行兼容性验证:
修改源码前适配情况
MariaDB10.1.34 | MariaDB10.1.34 | MariaDB10.1.41 | MariaDB10.1.48 | |
---|---|---|---|---|
server_audit.so | 1.4.0 | 1.4.4 | 1.4.7 | 1.4.7 |
MySQL5.7.39 | × | × | × | × |
MySQL5.7.34 | × | × | × | × |
MySQL5.7.33 | √ | √ | √ | √ |
修改源码后适配情况
MariaDB10.1.34 | MariaDB10.1.34 | MariaDB10.1.41 | MariaDB10.1.48 | |
---|---|---|---|---|
server_audit.so | 1.4.0 | 1.4.4 | 1.4.7 | 1.4.7 |
MySQL5.7.39 | √ | √ | √ | √ |
MySQL5.7.34 | √ | √ | √ | √ |
MySQL5.7.33 | √ | √ | √ | √ |
验证流程
- 安装三个版本的 MySQL(过程略)。
- 通过官网获取四个版本的 MariaDB 安装包。
- 解压安装包并获取
server_audit.so
。 - 为 MySQL 安装审计插件并验证可用性。
# 安装插件示例
# 获取 MariaDB 安装包
https://mariadb.org/download/# 上传并解压安装包
[root@10-186-60-13 10.1.11]# tar -zxvf mariadb-10.1.11-linux-glibc_214-x86_64
[root@10-186-60-13 10.1.11]# ll
total 509368
drwxr-xr-x 33 1001 1001 4096 Jan 28 2016 mariadb-10.1.11
drwxrwxr-x 13 1021 1004 321 Jan 29 2016 mariadb-10.1.11-linux-glibc_214-x86_64
-rw-r--r-- 1 root root 466400911 Jul 19 09:58 mariadb-10.1.11-linux-glibc_214-x86_64.tar.gz
-rw-r--r-- 1 root root 55184229 Jul 19 09:57 mariadb-10.1.11.tar.gz# 获取 server_audit.so
[root@10-186-60-13 10.1.11]# cd mariadb-10.1.11-linux-glibc_214-x86_64/lib/plugin/# 复制该插件到 MySQL 的 plugin 目录下并修改权限
[root@10-186-60-13 plugin]# cp server_audit.so /data/mysql/base/5.7.33/lib/plugin/
[root@10-186-60-13 plugin]# cd /data/mysql/base/5.7.33/lib/plugin/
[root@10-186-60-13 plugin]# chmod 755 server_audit.so# 登录到 MySQL 客户端进行插件的安装
[root@10-186-60-13 plugin]# /data/mysql/base/5.7.33/bin/mysql -uroot -p -S /data/mysql/data/3306/mysqld.sock
mysql> install plugin server_audit SONAME 'server_audit.so';
Query OK, 0 rows affected (0.01 sec)# 检查是否安装成功,若不兼容此时 MySQL 会发生 Crash
mysql> show plugins;
| SERVER_AUDIT | ACTIVE | AUDIT | server_audit.so | GPL
mysql> show plugins;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/data/mysql/data/3308/mysqld.sock' (111)
ERROR:
Can't connect to the server# 查看审计插件情况,开启审计插件,刷新审计插件 log 文件,验证插件可用性
mysql> show variables like'%audit%';
mysql> set global server_audit_logging=on;
mysql> set global server_audit_file_rotate_now =on;
Query OK, 0 rows affected (0.00 sec)# 检查 data 下是否有审计日志文件输出
[root@10-186-60-13 ~]# cd /data/mysql/data/3306/
[root@10-186-60-13 3306]# ll # 观察到有 server_audit.log 文件输出则插件开启成功
-rw-r----- 1 actiontech-mysql actiontech-mysql 53236 Jul 19 11:10 server_audit.log
-rw-r----- 1 actiontech-mysql actiontech-mysql 79363 Jul 19 11:10 server_audit.log.1# 卸载该审计插件,进行其他版本适配验证
mysql> uninstall plugin server_audit;# 检查插件可用状态,为 DELETED 则是卸载成功
mysql> show plugins;
| SERVER_AUDIT | DELETED | AUDIT | server_audit.so | GPL# 通过刷新审计日志验证是否卸载成功
mysql> set global server_audit_file_rotate_now =on;
ERROR 1193 (HY000): Unknown system variable 'server_audit_file_rotate_now'
[root@10-186-60-13 ~]# cd /data/mysql/base/5.7.33/lib/plugin/ # 删除审计插件,清理 log 文件,重启 MySQL
[root@10-186-60-13 plugin]# rm -rf server_audit.so
[root@10-186-60-13 3306]# rm -rf server_audit.log
[root@10-186-60-13 plugin]# systemctl restart mysqld_3306
注:参考以上步骤进行各个版本插件兼容性的检验,此处不再赘述。
发生 Crash
# 安装审计插件
mysql> install plugin server_audit SONAME 'server_audit.so';
ERROR 2013 (HY000): Lost connection to MySQL server during query# 检查插件安装情况
mysql> show plugins;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/data/mysql/data/3308/mysqld.sock' (111)
ERROR:
Can't connect to the server# 检查错误日志,发现发生了 Crash
Version: '5.7.39-log' socket: '/data/mysql/data/3308/mysqld.sock' port: 3308 MySQL Community Server (GPL)
230719 13:37:36 server_audit: MariaDB Audit Plugin version 1.4.7 STARTED.
05:37:36 UTC - mysqld got signal 11 ;
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
or misconfigured. This error can also be caused by malfunctioning hardware.
Attempting to collect some information that could help diagnose the problem.
As this is a crash and something is definitely wrong, the information
collection process might fail.
key_buffer_size=16777216
read_buffer_size=8388608
max_used_connections=23
max_threads=2000
thread_count=17
connection_count=17
It is possible that mysqld could use up to
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 20523165 K bytes of memory
Hope that's ok; if not, decrease some variables in the equation.
Thread pointer: 0x7fcf7469d380
Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
stack_bottom = 7fcfd411fe68 thread_stack 0x40000
/data/mysql/base/5.7.39/bin/mysqld(my_print_stacktrace+0x35)[0xf80e15]
/data/mysql/base/5.7.39/bin/mysqld(handle_fatal_signal+0x4b9)[0x7ff999]
/lib64/libpthread.so.0(+0xf6d0)[0x7fd0394ff6d0]
/data/mysql/base/5.7.39/lib/plugin/server_audit.so(get_db_mysql57+0x2f)[0x7fcfe32b852f]
/data/mysql/base/5.7.39/lib/plugin/server_audit.so(+0xb63b)[0x7fcfe32b863b]
/data/mysql/base/5.7.39/bin/mysqld(_Z18mysql_audit_notifyP3THD30mysql_event_general_subclass_tPKciS3_m+0x2f1)[0x801ff1]
/data/mysql/base/5.7.39/bin/mysqld(my_message_sql+0x134)[0x7f1be4]
/data/mysql/base/5.7.39/bin/mysqld(my_error+0xe0)[0xf7bc30]
/data/mysql/base/5.7.39/bin/mysqld(_ZN7handler11print_errorEii+0x641)[0x851c11]
/data/mysql/base/5.7.39/bin/mysqld[0xd66950]
/data/mysql/base/5.7.39/bin/mysqld(_ZN22Sql_cmd_install_plugin7executeEP3THD+0x23)[0xd66a53]
/data/mysql/base/5.7.39/bin/mysqld(_Z21mysql_execute_commandP3THDb+0xe50)[0xd41750]
/data/mysql/base/5.7.39/bin/mysqld(_Z11mysql_parseP3THDP12Parser_state+0x3cd)[0xd45c7d]
/data/mysql/base/5.7.39/bin/mysqld(_Z16dispatch_commandP3THDPK8COM_DATA19enum_server_command+0x1780)[0xd474a0]
/data/mysql/base/5.7.39/bin/mysqld(_Z10do_commandP3THD+0x194)[0xd48064]
/data/mysql/base/5.7.39/bin/mysqld(handle_connection+0x2ac)[0xe1b58c]
/data/mysql/base/5.7.39/bin/mysqld(pfs_spawn_thread+0x174)[0x143c5a4]
/lib64/libpthread.so.0(+0x7e25)[0x7fd0394f7e25]
/lib64/libc.so.6(clone+0x6d)[0x7fd037fb1bad]
Trying to get some variables.
Some pointers may be invalid and cause the dump to abort.
Query (7fcf74be91a0): install plugin server_audit SONAME 'server_audit.so'
Connection ID (thread ID): 300
Status: NOT_KILLED
The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains
information that should help you find out what is causing the crash.
解决方法
- 发生 Crash 后先恢复 MySQL 服务。
- 获取 MariaDB 编译包。
- 对 MariaDB 源码进行编译安装
- 获取编译后的
server_audit.so
并重新安装
# 发生 Crush 后先删除插件
[root@10-186-60-13 plugin]# rm -rf server_audit.so# 重启 MySQL 服务并进行登录验证
[root@10-186-60-13 plugin]# systemctl restart mysqld_3308
[root@10-186-60-13 plugin]# /data/mysql/base/5.7.39/bin/mysql -uroot -p -S /data/mysql/data/3308/mysqld.sock
获取 MariaDB 编译包
# 解压安装包
[root@10-186-60-13 mariadb-10.1.48]# yum install -y openssl libssl-dev build-essential bison libncurses-dev cmake gcc-gcc+ git ncurses-devel # 安装编译所需依赖
[root@10-186-60-13 10.1.48]# tar -zxvf mariadb-10.1.48.tar.gz
[root@10-186-60-13 10.1.48]# cd mariadb-10.1.48/plugin/server_audit/
[root@10-186-60-13 server_audit]# vim server_audit.c
修改 server_audit.c 文件内的相关代码
# 打开 server_audit.c 文件
db_off= 536; // 将 536 修改为 544,其他不变
db_len_off= 544; // 将 544 修改为 552,其他不变
然后保存退出。
# 返回源文件根目录进行编译安装
[root@10-186-60-13 server_audit]# cd ../..
cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DMYSQL_DATADIR=/mydata/data \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_ARCHIVE_STORAGE_ENGINE=1 \
-DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
-DWITH_READLINE=1 \
-DWITH_SSL=system \
-DWITH_ZLIB=system \
-DWITH_LIBWRAP=0 \
-DMYSQL_UNIX_ADDR=/tmp/mysql.sock \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci# 执行 make 进行编译安装
[root@10-186-60-13 server_audit]# make
注:编译完成后,重新安装插件即可,此处不再赘述。
编译后安装报错
在修改源码后进行编译安装遇到报错。
# MariaDB 10.1.41,插件版本为 1.4.7
mysql> install plugin server_audit SONAME 'server_audit.so';
ERROR 1030 (HY000): Got error 1 from storage engine
此时检查 mysql-error.log
发现无相关报错信息输出。
解决方法
通过测试,发现该问题可以通过重启 MySQL 解决。重启后,MySQL 会自动安装该插件,然后再开启插件即可。
总结
追溯该审计插件与 MySQL 5.7.34 版本不兼容的原因,其实还是因为 MariaDB 审计插件中 #ifdef __x86_64__
下的 db_off
与 db_len_off
的字符长度定义与 MySQL 不适配,所以在 MySQL 中安装该插件就会发生 Crash,通过修改 MariaDB 审计插件的源码进行编译安装即可解决该问题。
由于官方对 MariaDB 和 MySQL 并未做功能适配,故 MySQL 安装不同版本的审计插件可能还会出现其他问题导致 Crash,以上方法仅针对该版本安装时发生 Crash 的场景。
建议在使用该插件时选用 MariaDB 10.2.X、MariaDB 10.3.X 的最新版本来获取审计插件。
另外,由于审计插件与 MySQL 未适配的原因,您若是需要在生产环境下进行使用,请先进行版本适配验证,以免造成损失。
更多技术文章,请访问:https://opensource.actionsky.com/
关于 SQLE
爱可生开源社区的 SQLE 是一款面向数据库使用者和管理者,支持多场景审核,支持标准化上线流程,原生支持 MySQL 审核且数据库类型可扩展的 SQL 审核工具。
SQLE 获取
类型 | 地址 |
---|---|
版本库 | https://github.com/actiontech/sqle |
文档 | https://actiontech.github.io/sqle-docs/ |
发布信息 | https://github.com/actiontech/sqle/releases |
数据审核插件开发文档 | https://actiontech.github.io/sqle-docs/docs/dev-manual/plugins/howtouse |
相关文章:

MySQL5.7 与 MariaDB10.1 审计插件兼容性验证
这是一篇关于发现 MariaDB 审计插件导致 MySQL 发生 crash 后,展开适配验证并进行故障处理的文章。 作者:官永强 爱可生DBA 团队成员,擅长 MySQL 运维方面的技能。热爱学习新知识,亦是个爱打游戏的宅男。 本文来源:原创…...

PyTorch Lightning教程五:Debug调试
如果遇到了这样一个问题,当一次训练模型花了好几天,结果突然在验证或测试的时候崩掉了,这个时候其实是很奔溃的,主要还是由于没有提前知道哪些时候会出现什么问题,本节会引入Lightning的Debug方案 1.fast_dev_run参数 …...

末流211无科研保研经验分享
文章目录 个人背景夏令营哈工大威海西工大光电北航软院北邮计算机中科大科学岛 预推免东南软件北航计算机 写在最后心路历程寄语 个人背景 院校:末流211专业背景:计算机科学与技术排名:夏令营7 / 126,预推免3 / 126英语ÿ…...

日期选择器多选换行
<el-form-item label"日期选择"><div class"multi-date-picker"><div class"date-item"><span class"dateIcon"><el-icon><Calendar /></el-icon></span><span class"dateIt…...

NodeJS原型链污染ctfshow_nodejs
文章目录 NodeJS原型链污染&ctfshow_nodejs前言0x01.原型与原型链0x02.prototype和__proto__分别是什么?0x03.原型链继承不同对象的原型链* 0x04.原型链污染原理0x05.merge()导致原型链污染0x06.ejs模板引擎RCEejs模板引擎另一处rce 0x07.jade模板引擎RCE【ctfs…...

18. SpringBoot 如何在 POM 中引入本地 JAR 包
❤️ 个人主页:水滴技术 🌸 订阅专栏:成功解决 BUG 合集 🚀 支持水滴:点赞👍 收藏⭐ 留言💬 Spring Boot 是一种基于 Spring 框架的轻量级应用程序开发框架,它提供了快速开发应用程…...

vue2-$nextTick有什么作用?
1、$nextTick是什么? 官方定义:在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的DOM。 解释:Vue在更新DOM时是异步执行的,当数据发生变化时,Vue将开启一个异步更新的队…...

python自动收集粘贴板
win10的粘贴板可以用“winV”查看: 每次复制都相当于入栈一个字符串,粘贴相当于获取栈顶。 但是系统自带的这个粘贴板貌似不能一键导出,所以我写了个python代码完成这个功能: import pyperclip import timetmp while True:txt…...

Vue3_语法糖—— <script setup>以及unplugin-auto-import自动引入插件
<script setup>import { ref , onMounted} from vue;let obj ref({a: 1,b: 2,}); let changeObj ()>{console.log(obj)obj.value.c 3 //ref写法}onMounted(()>{console.log(obj)})</script> 里面的代码会被编译成组件 setup() 函数的内容。 相当于 <…...

2023-08-06力扣做过了的题
链接: 剑指 Offer 30. 包含min函数的栈 题意: 如题 解: 初级算法里做过的题 优化是存储和min的差值使得只需要n的栈和一个int min 实际代码: #include<bits/stdc.h> using namespace std; class MinStack { public:…...

进程间通信之管道
文章目录 一、管道1. 匿名管道2. 命名管道 进程具有独立性,因此进程间通信的前提是两个进程能看到同一份资源 一、管道 对于进程打开的内存文件,操作系统是以引用计数的方式创建的 file 结构体,如果让两个进程与同一个 file 结构体关联&…...

f12 CSS网页调试_css样式被划了黑线怎么办
我的问题是这样的 class加上去了,但是样式不生效,此时可能是样式被其他样式覆盖了, 解决方案就是 给颜色后边添加一个!important...

vue-制作自动滚动效果
第一步:下载 可以查看官方地址chenxuan0000 npm i vue-seamless-scroll -save 第二步:引用 import vueSeamlessScroll from "vue-seamless-scroll";//注册components: {vueSeamlessScroll,}, 第三步:使用 <vue-seamless…...

[国产MCU]-BL602-开发实例-DMA数据传输
DMA数据传输 文章目录 DMA数据传输1、DMA介绍2、DMA驱动API介绍3、DMA使用示例DMA(Direct Memory Access)是一种内存存取技术,可以独立地直接读写系统内存,而不需处理器介入处理。 在同等程度的处理器负担下,DMA是一种快速的数据传送方式。 BL602的DMA控制器有4组独立专用通…...

Redis压缩列表
区分一下 3.2之前 Redis中的List有两种编码格式 一个是LINKEDLIST 一个是ZIPLIST 这个ZIPLIST就是压缩列表 3.2之后来了一个QUICKLIST QUICKLIST是ZIPLIST和LINKEDLIST的结合体 也就是说Redis中没有ZIPLIST和LINKEDLIST了 然后在Redis5.0引入了LISTPACK用来替换QUiCKLIST中的…...

【SA8295P 源码分析】62 - Android GVM Kernel 内核 make bootimage 过程分析
【SA8295P 源码分析】62 - Android GVM Kernel 内核 make bootimage 过程分析 一、make bootimage 命令执行过程分析1.1 source buid/envsetup.sh 分析1.2 lunch msmnile_gvmq-userdebug 分析1.3 make bootimage:step 1 之 加载配置文件过程分析1.4 make bootimage:step 2 之…...

机器学习——SMO算法推导与实践
一、 硬间隔-SMO算法推导 明天再说,啊。。。。感觉天空明朗了很多,即使现在已经很晚了 还是要打开柯南,看看电视,等待天气预报所说的台风天吧! 一时之间,忽然失去了用markdown语法写下推导过程的勇气。。。…...

mac的终端通过code .指令快速启动vscode
通过在vscode中安装"code"命令工具 打开vsocode,使用快捷键⇧⌘P,然后输入shell,会弹出来“Shell命令:在PATH中安装‘code’命令”浮窗,选择安装就可以了,然后就可以在终端通过code .来快速启动…...

前端系统使用iframe下载文件
需求描述 前端调用后端的接口,获取到文件的路径,并下载。 碰到的问题 页面组件存在与云端的组件库,使用window.open()无法满足需求(在当前页面下载),因为路径是跨域的,所以决定使用iframe的方…...

RabbitMQ - 简单案例
目录 0.引用 1.Hello world 2.轮训分发消息 2.1 抽取工具类 2.2 启动两个工作线程接受消息 2.4 结果展示 3.消息应答 3.1 自动应答 3.2 手动消息应答的方法 3.3 消息自动重新入队 3.4 消息手动应答代码 4.RabbitMQ 持久化 4.1 队列如何实现持久化 4.2 消息实现持久化 5.不…...

《吐血整理》高级系列教程-吃透Fiddler抓包教程(30)-Fiddler如何抓Android7.0以上的Https包-番外篇
1.简介 通过宏哥前边几篇文章的讲解和介绍想必大家都知道android7.0以上,有android的机制不在信任用户证书,导致https协议无法抓包。除非把证书装在系统信任的证书里,此时手机需要root权限。但是大家都知道root手机是非常繁琐的且不安全&…...

服务器被攻击了怎么办?
服务器被攻击是无法避免的,但是我们能通过做好防护措施,提高服务器的安全性,降低被攻击的几率。那么当服务器已经被 攻击了,怎样才能降低损失呢?该怎样补救? 断开网络 全部的攻击都来自于网络,因…...

P1156 垃圾陷阱(背包变形)
垃圾陷阱 题目描述 卡门――农夫约翰极其珍视的一条 Holsteins 奶牛――已经落了到 “垃圾井” 中。“垃圾井” 是农夫们扔垃圾的地方,它的深度为 D D D( 2 ≤ D ≤ 100 2 \le D \le 100 2≤D≤100)英尺。 卡门想把垃圾堆起来,…...

[Docker实现测试部署CI/CD----构建成功后钉钉告警(7)]
目录 15、钉钉告警创建项目群,然后添加机器人添加机器人Jenkins 系统配置项目配置修改Jenkinsfile文件,添加钉钉提示信息测试 不修改Jenkinsfile文件,添加钉钉提示信息测试 15、钉钉告警 创建项目群,然后添加机器人 首先需要在钉…...

UE5 半透明覆层材质
文章目录 前言介绍示例1示例2示例3 前言 本文采用虚幻5.2.1版本演示,介绍半透明覆层材质(覆层材质)。 介绍 半透明覆层材质是 UE5.1 版本 更新的功能,使用半透明覆层材质,可以轻松的给物体表面附着一层材质。 在UE5…...

在Raspberry Pi 4上安装Ubuntu 20.04 + ROS noetic(不带显示器)
在Raspberry Pi 4上安装Ubuntu 20.04 ROS noetic(不带显示器) 1. 所需设备 所需设备: 树莓派 4 B 型 wifi microSD 卡:最小 32GB MicroSD 转 SD 适配器 (可选)显示器,鼠标等 2. 树莓派…...

CommStudio for .NET Crack
CommStudio for .NET Crack CommStudio for.NET使您的应用程序可以轻松地使用串行端口和调制解调器进行通信。CommStudio for.NET是一套全面的组件和可视化调试工具,可将远程系统和设备与visual Studio 2005和visual Studio 2008集成。开发与遗留系统和外部设备集成…...

蓝桥杯上岸考点清单 (冲刺版)!!!
大家好 我是寸铁💪 真题千千万万遍,蓝桥省一自然现! ✌️ 日更3000里,蓝桥眷顾你 🌟 暴力出奇迹,打表过样例 👊 冲刺蓝桥杯省一模板大全来啦 🔥 蓝桥杯4月8号就要开始了 &#…...

AI一键生成短视频
AI一键生成推文短视频 阅读时长:10分钟 本文内容: 结合开源AI,一键生成短视频发布到常见的某音,某手平台,狠狠赚一笔 前置知识: 1.基本的 python 编程知识 2.chatGPT 使用过 3.stable diffution 使用过 成果…...

基于MATLAB长时间序列遥感数据分析(以MODIS数据处理为例)
MATLAB MATLAB是美国MathWorks公司出品的商业数学软件,用于数据分析、无线通信、深度学习、图像处理与计算机视觉、信号处理、量化金融与风险管理、机器人,控制系统等领域。 [1] MATLAB是matrix&laboratory两个词的组合,意为矩阵工厂&a…...