MariaDB与MySQL对比 --- 对分布式事务的支持
MariaDB和MySQL两者对分布式事务的支持有所不同,总的来说MySQL的支持更好,是完备的和可靠的(也发现了一个bug),而MariaDB的支持还有诸多问题,先举例说明。
本文测试用例使用MySQL-5.7.16和MariaDB-10.1.9 进行测试。
MySQL/MariaDB对分布式事务的支持是根据 X/Open CAE document Distributed Transaction Processing: The XA Specification (http://www.opengroup.org/public/pubs/catalog/c193.htm) ,主要包括下面这几个语句:
xa start 'gtid';
xa end 'gtid';
xa prepare 'gtid';
xa commit 'gtid';
xa rollback 'gtid';
xa recover;
外部的分布式事务管理器(transaction manager, TM) 可以使用这套XA命令来操作mysql 数据库,按照XA标准的两阶段提交算法(2PC) 完成分布式事务提交。各个语句的意义见官方文档。
其中mariadb的问题在于 xa prepare 'gtid' 之后,这个事务分支(transaction branch) 可能会丢失。详见下文。
事先创建1个简单的表并且插入4行数据:
create table t1(a int primary key);
insert into t1 values(1),(2),(3),(4);
一。两者的公共行为(相同点)
本节的查询是要说明,xa prepare之前(无论是xa end 之前还是之后),xa事务的改动对外部不可见,也不持久化,退出连接就会丢失修改。xa事务信息本身也会在退出连接后消失,重新连接后xa recover不会显示它。
这些行为mysql与mariadb相同,都是正确的。
mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> xa start '124';
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t1 values(5);
Query OK, 1 row affected (0.00 sec)
mysql> insert into t1 values(6);
Query OK, 1 row affected (0.00 sec)
mysql> quit;
Bye
david@david-VirtualBox:~/mysql_installs/mysql-5.7.16$ ./bin/mysql -S ../../mysql-instances/a/mysql.sock
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.7.16-debug-log Source distribution
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> xa recover;
Empty set (0.00 sec)
mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> xa start '124';
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t1 values(5);
Query OK, 1 row affected (0.00 sec)
mysql> insert into t1 values(6);
Query OK, 1 row affected (0.00 sec)
mysql> xa end '124';
Query OK, 0 rows affected (0.00 sec)
mysql> quit;
Bye
david@david-VirtualBox:~/mysql_installs/mysql-5.7.16$ ./bin/mysql -S ../../mysql-instances/a/mysql.sock
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.7.16-debug-log Source distribution
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> xa recover;
Empty set (0.00 sec)
mysql> select*from t1;
ERROR 1046 (3D000): No database selected
mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select*from t1;
+------+
| a |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
+------+
4 rows in set (0.00 sec)
二。MySQL的XA PREPARE 的行为
1. 对MySQL来说,在一个事务中执行xa prepare之后退出连接,xa事务不丢失,它的更新也不会丢失。
mysql> create table t1(a int);
Query OK, 0 rows affected (0.05 sec)
mysql> xa start '123';
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t1 values(1),(2);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> insert into t1 values(3),(4);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> xa end '123';
Query OK, 0 rows affected (0.00 sec)
mysql> xa prepare '123';
Query OK, 0 rows affected (0.07 sec)
mysql> quit;
Bye
david@david-VirtualBox:~/mysql_installs/mysql-5.7.16$ ./bin/mysql -S ../../mysql-instances/a/mysql.sock
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.16-debug-log Source distribution
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> xa recover;
+----------+--------------+--------------+------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+------+
| 1 | 3 | 0 | 123 |
+----------+--------------+--------------+------+
1 row in set (0.00 sec)
mysql> xa commit '123';
Query OK, 0 rows affected (0.01 sec)
mysql> select*From test.t1;
+------+
| a |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
+------+
4 rows in set (0.00 sec)
2. 对mysql来说,在一个事务中执行xa prepare后,kill掉 mysqld ,xa 事务的改动及其元数据不丢失,mysql binlog系统与innodb做了协调一致的事务恢复,非常完美。重启mysqld后,客户端连接上去,执行xa recover可以看到这个prepared事务,执行 xa commit 可以完成该事务的提交。
mysql> xa start '124';
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t1 values(5);
Query OK, 1 row affected (0.00 sec)
mysql> insert into t1 values(6);
Query OK, 1 row affected (0.00 sec)
mysql> xa end '124';
Query OK, 0 rows affected (0.00 sec)
mysql> xa prepare '124';
Query OK, 0 rows affected (0.00 sec)
mysql> quit;
Bye
david@david-VirtualBox:~/mysql_installs/mysql-5.7.16$ ./bin/mysql -S ../../mysql-instances/a/mysql.sock
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 5.7.16-debug-log Source distribution
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> xa recover;
+----------+--------------+--------------+------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+------+
| 1 | 3 | 0 | 124 |
+----------+--------------+--------------+------+
1 row in set (0.00 sec)
mysql> quit
Bye
[1]+ Killed ./bin/mysqld_safe --defaults-file=../../mysql-instances/a/my.cnf
david@david-VirtualBox:~/mysql_installs/mysql-5.7.16$ ./bin/mysqld_safe --defaults-file=../../mysql-instances/a/my.cnf &
[1] 22109
david@david-VirtualBox:~/mysql_installs/mysql-5.7.16$ 2016-12-02T06:53:49.336023Z mysqld_safe Logging to '/home/david/mysql-instances/a/datadir/david-VirtualBox.err'.
2016-12-02T06:53:49.350561Z mysqld_safe Starting mysqld daemon with databases from /home/david/mysql-instances/a/datadir
david@david-VirtualBox:~/mysql_installs/mysql-5.7.16$ ./bin/mysql -S ../../mysql-instances/a/mysql.sock
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.16-debug-log Source distribution
Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> xa recover;
+----------+--------------+--------------+------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+------+
| 1 | 3 | 0 | 124 |
+----------+--------------+--------------+------+
1 row in set (0.00 sec)
mysql> select*from t1;
ERROR 1046 (3D000): No database selected
mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> select*from t1;
+------+
| a |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
+------+
4 rows in set (0.00 sec)
mysql> xa commit '124';
Query OK, 0 rows affected (0.00 sec)
mysql> select*from t1;
+------+
| a |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
+------+
6 rows in set (0.00 sec)
mysql>
3. mysql之所以能做到上述行为,是因为mysql在xa prepare 做了binlog刷盘,并且允许其后的xa commit被其他事务的binlog隔开。
本例中,新启动一个xa事务 T1,在xa prepare 之后,另启动一个连接在其中执行2个普通本地事务,然后再做xa commit T1,可以看到这个xa commit 的binlog与xa prepare被那两个新事务的binlog隔开了。对MySQL来说这不是问题。
三。MariaDB的XA支持
mariadb 在 xa prepare时候不会刷盘binlog,因此xa prepare 之后,这个事务的binlog仍然可能丢失。
1. xa prepare 后连接断开,那么这个prepared事务就消失了,包括事务修改数据和元数据。binlog上面没有它的binlog,xa recover也不能列出这个事务。
MariaDB [(none)]> xa start '124';
Query OK, 0 rows affected (0.00 sec)
MariaDB [(none)]> insert into t1 values(5);
ERROR 1046 (3D000): No database selected
MariaDB [(none)]> use test;
Database changed
MariaDB [test]> insert into t1 values(5);
Query OK, 1 row affected (0.00 sec)
MariaDB [test]> insert into t1 values(6);
Query OK, 1 row affected (0.00 sec)
MariaDB [test]> xa end '124';
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> xa prepare '124';
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> xa recover;
+----------+--------------+--------------+------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+------+
| 1 | 3 | 0 | 124 |
+----------+--------------+--------------+------+
1 row in set (0.00 sec)
MariaDB [test]> quit;
Bye
[tdengine@TENCENT64 ~/davie/mysql_installs/tdsql-mariadb-10.1.9-bin-release3/install]$./jmysql.sh 6678
cmd: e
/data/6678/prod/mysql.sock
/data/home/tdengine/davie/mysql_installs/tdsql-mariadb-10.1.9-bin-release3
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 9
Server version: 10.1.9-MariaDBV1.0R030D002-20161123-1511 Source distribution
Copyright (c) 2000, 2015, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> xa recover;
Empty set (0.00 sec)
MariaDB [(none)]> use test;
Database changed
MariaDB [test]> select*from t1;
Empty set (0.00 sec)
MariaDB [test]>
2. xa prepare 后kill掉mysqld,那么这个prepared事务在binlog上面不存在,不过xa recover能列出这个事务,并且它的改动也存在。
在innodb当中,执行了XA PREPARE之后,这个事务已经prepare了,但是它的binlog没有写到binlog文件中。mysqld被kill掉重新拉起后,innodb做了事务恢复,所以可以看到它之前的改动;但是binlog上面却没有这个事务。不过binlog replication 可以找到这个事务,所以 xa recover 可以列出来,并且做xa commit 可以提交这个事务。之后,这个事务的改动就可见了。但是,innodb中的数据与binlog已经不一致了。
MariaDB [test]> xa start '125';
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> insert into t1 values(9);
Query OK, 1 row affected (0.00 sec)
MariaDB [test]> insert into t1 values(10);
Query OK, 1 row affected (0.00 sec)
MariaDB [test]> xa end '125';
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> xa prepare '125';
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> quit
Bye
[tdengine@TENCENT64 ~/davie/mysql_installs/tdsql-mariadb-10.1.9-bin-release3/install]$./jmysql.sh 6678
cmd: e
/data/6678/prod/mysql.sock
/data/home/tdengine/davie/mysql_installs/tdsql-mariadb-10.1.9-bin-release3
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 3
Server version: 10.1.9-MariaDBV1.0R030D002-20161123-1511 Source distribution
Copyright (c) 2000, 2015, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> xa recover;
+----------+--------------+--------------+------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+------+
| 1 | 3 | 0 | 125 |
+----------+--------------+--------------+------+
1 row in set (0.00 sec)
MariaDB [(none)]> select*from t1;
ERROR 1046 (3D000): No database selected
MariaDB [(none)]> use test;
Database changed
MariaDB [test]> select*from t1;
+---+
| a |
+---+
| 5 |
| 6 |
| 7 |
| 8 |
+---+
4 rows in set (0.01 sec)
MariaDB [test]> xa commit '125';
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> select*from t1;
+----+
| a |
+----+
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
+----+
6 rows in set (0.00 sec)
MariaDB [test]>
从最初的测例开始,一直没有任何插入数据行的binlog(write_row)写入。
微信扫一扫
关注该公众号