您的当前位置:首页MySQL 5.7 并行复制实现原理与调优

MySQL 5.7 并行复制实现原理与调优

2023-11-10 来源:六九路网
,coordinator线程主要负责以前两部分的内容:

  • 若判断可以并行执行,那么选择worker线程执行事务的二进制日志
  • 若判断不可以并行执行,如该操作是DDL,亦或者是事务跨schema操作,则等待所有的worker线程执行完成之后,再执行当前的日志
  • 这意味着 coordinator线程并不是仅将日志发送给worker线程,自己也可以回放日志,但是所有可以并行的操作交付由worker线程完成。coordinator线程与worker是典型的生产者与消费者模型。

    (疑问:这里是在判断不可以并行执行时,在等待所有的worker线程执行完成后,是由coordinator执行还是由worker进程非并行进行。从上面两句话中看不出coordinator进程回放日志。)

    上述机制实现了基于schema的并行复制存在两个问题,首先是crash safe功能不好做,因为可能之后执行的事务由于并行复制的关系先完成执行,那么当发生crash的时候,这部分的处理逻辑是比较复杂的。从代码上看,5.6这里引入了Low-Water-Mark标记来解决该问题,从设计上看( WL#5569 ),其是希望借助于日志的幂等性来解决该问题,不过5.6的二进制日志回放还不能实现幂等性。另一个最为关键的问题是这样设计的并行复制效果并不高,如果用户实例仅有一个库,那么就无法实现并行回放,甚至性能会比原来的单线程更差。而 单库多表是比多库多表更为常见的一种情形 。

    MySQL 5.7并行复制原理

    MySQL 5.7基于组提交的并行复制

    MySQL 5.7才可称为真正的并行复制,这其中最为主要的原因就是slave服务器的回放与主机是一致的即master服务器上是怎么并行执行的slave上就怎样进行并行回放。不再有库的并行复制限制,对于二进制日志格式也无特殊的要求(基于库的并行复制也没有要求)。

    从MySQL官方来看,其并行复制的原本计划是支持表级的并行复制和行级的并行复制,行级的并行复制通过解析ROW格式的二进制日志的方式来完成, WL#4648 。但是最终出现给小伙伴的确是在开发计划中称为:MTS: Prepared transactions slave parallel applier,可见: WL#6314 。该并行复制的思想最早是由MariaDB的Kristain提出,并已在MariaDB 10中出现,相信很多选择MariaDB的小伙伴最为看重的功能之一就是并行复制。

    MySQL 5.7并行复制的思想简单易懂,一言以蔽之: 一个组提交的事务都是可以并行回放 ,因为这些事务都已进入到事务的prepare阶段,则说明事务之间没有任何冲突(否则就不可能提交)。

    为了兼容MySQL 5.6基于库的并行复制,5.7引入了新的变量slave-parallel-type,其可以配置的值有:

  • DATABASE:默认值,基于库的并行复制方式
  • LOGICAL_CLOCK:基于组提交的并行复制方式
  • 支持并行复制的GTID

    如何知道事务是否在一组中,又是一个问题,因为原版的MySQL并没有提供这样的信息。在MySQL 5.7版本中,其设计方式是将组提交的信息存放在GTID中。那么如果用户没有开启GTID功能,即将参数gtid_mode设置为OFF呢?故MySQL 5.7又引入了称之为Anonymous_Gtid的二进制日志event类型,如:

    mysql> SHOW BINLOG EVENTS in ‘mysql-bin.000006‘;+------------------+-----+----------------+-----------+-------------+-----------------------------------------------+| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |+------------------+-----+----------------+-----------+-------------+-----------------------------------------------+| mysql-bin.000006 | 4 | Format_desc | 88 | 123 | Server ver: 5.7.7-rc-debug-log, Binlog ver: 4 || mysql-bin.000006 | 123 | Previous_gtids | 88 | 194 | f11232f7-ff07-11e4-8fbb-00ff55e152c6:1-2 || mysql-bin.000006 | 194 | Anonymous_Gtid | 88 | 259 | SET @@SESSION.GTID_NEXT= ‘ANONYMOUS‘ || mysql-bin.000006 | 259 | Query | 88 | 330 | BEGIN || mysql-bin.000006 | 330 | Table_map | 88 | 373 | table_id: 108 (aaa.t) || mysql-bin.000006 | 373 | Write_rows | 88 | 413 | table_id: 108 flags: STMT_END_F |......

     

    这意味着在 MySQL 5.7版本中即使不开启GTID,每个事务开始前也是会存在一个Anonymous_Gtid ,而这GTID中就存在着组提交的信息。

    LOGICAL_CLOCK

    然而,通过上述的SHOW BINLOG EVENTS,我们并没有发现有关组提交的任何信息。但是通过mysqlbinlog工具,用户就能发现组提交的内部信息:

    root@localhost:~# mysqlbinlog mysql-bin.0000006 | grep last_committed#150520 14:23:11 server id 88 end_log_pos 259 CRC32 0x4ead9ad6 GTID last_committed=0 sequence_number=1#150520 14:23:11 server id 88 end_log_pos 1483 CRC32 0xdf94bc85 GTID last_committed=0 sequence_number=2#150520 14:23:11 server id 88 end_log_pos 2708 CRC32 0x0914697b GTID last_committed=0 sequence_number=3#150520 14:23:11 server id 88 end_log_pos 3934 CRC32 0xd9cb4a43 GTID last_committed=0 sequence_number=4#150520 14:23:11 server id 88 end_log_pos 5159 CRC32 0x06a6f531 GTID last_committed=0 sequence_number=5#150520 14:23:11 server id 88 end_log_pos 6386 CRC32 0xd6cae930 GTID last_committed=0 sequence_number=6#150520 14:23:11 server id 88 end_log_pos 7610 CRC32 0xa1ea531c GTID last_committed=6 sequence_number=7#150520 14:23:11 server id 88 end_log_pos 8834 CRC32 0x96864e6b GTID last_committed=6 sequence_number=8#150520 14:23:11 server id 88 end_log_pos 10057 CRC32 0x2de1ae55 GTID last_committed=6 sequence_number=9#150520 14:23:11 server id 88 end_log_pos 11280 CRC32 0x5eb13091 GTID last_committed=6 sequence_number=10#150520 14:23:11 server id 88 end_log_pos 12504 CRC32 0x16721011 GTID last_committed=6 sequence_number=11#150520 14:23:11 server id 88 end_log_pos 13727 CRC32 0xe2210ab6 GTID last_committed=6 sequence_number=12#150520 14:23:11 server id 88 end_log_pos 14952 CRC32 0xf41181d3 GTID last_committed=12 sequence_number=13...

     

    可以发现较之原来的二进制日志内容多了last_committed和sequence_number,last_committed表示事务提交的时候,上次事务提交的编号,如果事务具有相同的last_committed,表示这些事务都在一组内,可以进行并行的回放。例如上述last_committed为0的事务有6个,表示组提交时提交了6个事务,而这6个事务在从机是可以进行并行回放的。

    上述的last_committed和sequence_number代表的就是所谓的LOGICAL_CLOCK。先来看源码中对于LOGICAL_CLOCK的定义:

    class Logical_clock{ private: int64 state; /* Offset is subtracted from the actual "absolute time" value at logging a replication event. That is the event holds logical timestamps in the "relative" format. They are meaningful only in the context of the current binlog. The member is updated (incremented) per binary log rotation. */ int64 offset; ......

     

    state是一个自增的值,offset在每次二进制日志发生rotate时更新,记录发生rotate时的state值。其实state和offset记录的是全局的计数值,而存在二进制日志中的仅是当前文件的相对值。使用LOGICAL_CLOCK的场景如下:

    class MYSQL_BIN_LOG: public TC_LOG{ ... public: /* Committed transactions timestamp */ Logical_clock max_committed_transaction; /* "Prepared" transactions timestamp */ Logical_clock transaction_counter; ...

     

    可以看到在类MYSQL_BIN_LOG中定义了两个Logical_clock的变量:

  • max_committed_transaction:记录上次组提交时的logical_clock,代表上述mysqlbinlog中的last_committed
  • transaction_counter:记录当前组提交中各事务的logcial_clock,代表上述mysqlbinlog中的sequence_number
  • 并行复制测试

    下图显示了开启MTS后,slave服务器的QPS。测试的工具是sysbench的单表全update测试,测试结果显示在16个线程下的性能最好,从机的QPS可以达到25000以上,进一步增加并行执行的线程至32并没有带来更高的提升。而原单线程回放的QPS仅在4000左右,可见MySQL 5.7 MTS带来的性能提升,而由于测试的是单表,所以MySQL 5.6的MTS机制则完全无能为力了。

    技术分享

    并行复制配置与调优

    master_info_repository

    开启MTS功能后,务必将参数master_info_repostitory设置为TABLE,这样性能可以有50%~80%的提升。这是因为并行复制开启后对于元master.info这个文件的更新将会大幅提升,资源的竞争也会变大。在之前 InnoSQL 的版本中,添加了参数来控制刷新master.info这个文件的频率,甚至可以不刷新这个文件。因为刷新这个文件是没有必要的,即根据master-info.log这个文件恢复本身就是不可靠的。在MySQL 5.7中,Inside君推荐将master_info_repository设置为TABLE,来减小这部分的开销。

    slave_parallel_workers

    若将slave_parallel_workers设置为0,则MySQL 5.7退化为原单线程复制,但将slave_parallel_workers设置为1,则SQL线程功能转化为coordinator线程,但是只有1个worker线程进行回放,也是单线程复制。然而,这两种性能却又有一些的区别,因为多了一次coordinator线程的转发,因此slave_parallel_workers=1的性能反而比0还要差,在Inside君的测试下还有20%左右的性能下降,如下图所示:

    技术分享

    这里其中引入了另一个问题,如果主机上的负载不大,那么组提交的效率就不高,很有可能发生每组提交的事务数量仅有1个,那么在从机的回放时, 虽然开启了并行复制,但会出现性能反而比原先的单线程还要差的现象,即延迟反而增大了 。聪明的小伙伴们,有想过对这个进行优化吗?

    Enhanced Multi-Threaded Slave配置

    说了这么多,要开启enhanced multi-threaded slave其实很简单,只需根据如下设置:

    # slaveslave-parallel-type=LOGICAL_CLOCKslave-parallel-workers=16master_info_repository=TABLErelay_log_info_repository=TABLErelay_log_recovery=ON
    并行复制监控

    复制的监控依旧可以通过SHOW SLAVE STATUSG,但是MySQL 5.7在performance_schema架构下多了这些表,用户可以更细力度的进行监控:

    mysql> show tables like ‘replication%‘;+---------------------------------------------+| Tables_in_performance_schema (replication%) |+---------------------------------------------+| replication_applier_configuration || replication_applier_status || replication_applier_status_by_coordinator || replication_applier_status_by_worker || replication_connection_configuration || replication_connection_status || replication_group_member_stats || replication_group_members |+---------------------------------------------+8 rows in set (0.00 sec)
    总结

    MySQL 5.7推出的Enhanced Multi-Threaded Slave解决了困扰MySQL长达数十年的复制延迟问题,再次提醒一些无知的PostgreSQL用户,不要再停留在之前对于MySQL的印象,物理复制也不一定肯定比逻辑复制有优势,而MySQL 5.7的MTS已经完全可以解决延迟问题。anyway,和Inside君一起见证划时代MySQL 5.7 GA版本的降临吧.

     

     

    注:

    1、Coordinator thread on slave dispatches work across several worker threads。Each worker thread commits trx in isolation。

    2、mysql 5.6的MTS是基于库级别的并行,当有多个数据库时,可以将slave_parallel_workers设置为数据库的数量,为了避免新建库后来回修改,也可以将该参数设置的大一些。设置为库级别的事务时,不允许这样做,会报错。

    3、mysql 5.7 后的MTS可以实现更小粒度的并行复制,但需要将slave_parallel_type设置为LOGICAL_CLOCK,但仅仅设置为LOGICAL_CLOCK也会存在问题,因为此时在slave上应用事务的顺序是无序的,和relay log中记录的事务顺序不一样,这样数据一致性是无法保证的,为了保证事务是按照relay log中记录的顺序来回放,就需要开启参数slave_preserve_commit_order。开启该参数后,the executing thread waits until all previous transactions are committed before committing. While the slave thread is waiting for other workers to commit their transactions it reports its status as Waiting for preceding transaction to commit.

    所以虽然mysql5.7添加MTS后,虽然slave可以并行应用relay log,但commit部分仍然是顺序提交,其中可能会有等待的情况。

     

    当开启slave_preserve_commit_order参数后,slave_parallel_type只能是LOGICAL_CLOCK,如果你有使用级联复制,那LOGICAL_CLOCK可能会使离master越远的slave并行性越差。

    Regardless of the value of this variable, there is no special configuration required on the master. When slave_preserve_commit_order=1, you can only use LOGICAL_CLOCK. If your replication topology uses multiple levels of slaves, LOGICAL_CLOCK may achieve less parallelization for each level the slave is away from the master.

    4、5.7中会在binlog中额外加入元数据,来划分那些事务可以并行执行。

    Additional metadata is stored in the binlogs to identify transactions that can be applied in parallel

    而slave则通过 coordinator 线程从relay log中抽取元数据,进而分发给worker线程并行执行的事务组。

    The coordinator thread is able to extract the metadata from the relay logs to dispatch the transactions across workers

    5、SHOW SLAVE STATUS适用于single sql thread,但在使用了MTS后,如果多个线程出现问题时,会不方便查看。在5.7的performance_schema数据库中,新加了一个监控replication的部分表:
    mysql> show tables like ‘replication%‘;+---------------------------------------------+| Tables_in_performance_schema (replication%) |+---------------------------------------------+| replication_applier_configuration || replication_applier_status || replication_applier_status_by_coordinator || replication_applier_status_by_worker || replication_connection_configuration || replication_connection_status || replication_group_member_stats || replication_group_members |+---------------------------------------------+8 rows in set (0.00 sec)

    通过replication_applier_status_by_worker可以看到worker进程的工作情况:

    mysql> mysql> select * from replication_applier_status_by_worker;+--------------+-----------+-----------+---------------+--------------------------------------------+-------------------+--------------------+----------------------+| CHANNEL_NAME | WORKER_ID | THREAD_ID | SERVICE_STATE | LAST_SEEN_TRANSACTION | LAST_ERROR_NUMBER | LAST_ERROR_MESSAGE | LAST_ERROR_TIMESTAMP |+--------------+-----------+-----------+---------------+--------------------------------------------+-------------------+--------------------+----------------------+| | 1 | 32 | ON | 0d8513d8-00a4-11e6-a510-f4ce46861268:96604 | 0 | | 0000-00-00 00:00:00 || | 2 | 33 | ON | 0d8513d8-00a4-11e6-a510-f4ce46861268:97760 | 0 | | 0000-00-00 00:00:00 |+--------------+-----------+-----------+---------------+--------------------------------------------+-------------------+--------------------+----------------------+2 rows in set (0.00 sec)

    其他各表的使用参考官方文档。

     6、group commit: This optimization reduces the number of operations needed to produce the binary logs by grouping transactions. When transactions are committing at the same time, they are written to the binary log in a single operation. But if transactions commit at the same time, then they are not sharing any locks, which means they are not conflicting thus can be executed in parallel on slaves. So by adding group commit information in the binary logs on the master, the slaves can safely run transactions in parallel.7、涉及到组提交的一个延时控制参数:binlog_group_commit_sync_delay

     

    Controls how many microseconds the binary log commit waits before synchronizing the binary log file to disk. By default binlog-group-commit-sync-delay is set to 0, meaning that there is no delay. Setting binlog-group-commit-sync-delay to a microsecond delay enables more transactions to be synchronized together to disk at once, reducing the overall time to commit a group of transactions because the larger groups require fewer time units per group. With the correct tuning, this can increase slave performance without compromising the master‘s throughput.

    8、讨论技术就讨论技术,没必要踩低别人来抬高自己,而且不了解pg就妄论pg是可笑的。类比Linus那句话:“Talk is cheap,show your test.”

     

    参考:

    http://mp.weixin.qq.com/s?__biz=MjM5MjIxNDA4NA==&mid=205236417&idx=1&sn=15281c834348911cea106478aa819175&scene=23&srcid=0525zwrE6gRYCIPgKxoq40iN#rd

    http://blog.booking.com/better_parallel_replication_for_mysql.html

    https://www.percona.com/resources/technical-presentations/multi-threaded-replication-mysql-56-and-57-percona-technical-mysql

    https://dev.mysql.com/doc/refman/5.7/en/replication-options-slave.html#option_mysqld_slave-parallel-type

    https://dev.mysql.com/doc/refman/5.7/en/replication-options-slave.html#sysvar_slave_preserve_commit_order

    https://dev.mysql.com/doc/refman/5.7/en/replication-options-binary-log.html#sysvar_binlog_group_commit_sync_delay

    MySQL 5.7 并行复制实现原理与调优

    标签:

    小编还为您整理了以下内容,可能对您也有帮助:

    pgsql的主键存储方式

    PostgreSQL的稳定性极强,Innodb等索引在崩溃,断电之类的灾难场景下 抗击打能力有了长足进步,然而很多 MqSQL用户 都遇到过 Server级的数据库丢失的场景 -- MySQL系统库是 MyISAM,相比之下,PG数据库这方面要更好一些。

    任何系统都有它的性能极限,在高并发读写,负载近极限下,PG的性能指标仍可以位置双曲线甚至对数曲线,到 顶峰之后不在下降,而MySQL明显出现一个波峰后下滑(5.5版本 之后,在企业级版本中有个插件可以改善很多,不过需要付费)。

    PG多年来在 GIS(地理信息)领域处于优势地位,因为它有丰富的几何类型,PG有大量字典,数组,bitmap等数据类型,相比之下 MySQL就差很多, Instagram就是因为 PG的空间数据库 扩展 POSTGIS远远强于 MySQL的 my spatial 而采用 PgSQL的。

    PG的“无锁定”特性非常突出,甚至包括 vacuum这样的整理数据空间的操作,这个和PGSQL的MVCC实现有关系。

    PG可以使用函数 和 条件索引,这使得 PG数据库的调优非常灵活, MySQL就没有这个功能,条件索引在 web应用中 很重要。

    PG有极其强悍的 SQL编程能力(9.x 图灵完备,支持递归!),有非常丰富的统计函数和统计语法支持,比如分析函数(Oracle的叫法,PG里叫Window函数),还可以用多种语言来写存储过程,对于 R的支持也很好。这一点MySQL就差很多,很多分析功能都不支持,腾讯内部的存储主要是 MySQL,但是数据分析主要是 Hadoop+ PgSQL。

    PG的有多种集群架构可以选择,plproxy可以之hi语句级的镜像或分片,slony可以进行字段级的同步配置,standby 可以构建 WAL文件级或流式的读写分离集群,同步频率和集群策略调整方便。

    一般关系型数据库字符串有长度 8k 左右,无限长 TEXT类型的功能受限,只能作为外部大数据访问。而 PG 的 TEXT 类型 可以直接访问且无长度, SQL语法内置 正则表达式,可以索引,还可以全文检索,或使用 xml xpath。用 PG的话,文档数据库都可以省了。

    PgSQL对于 numa 架构的支持比 MySQL强一些,比 MySQL对于读的性能更好一些, PgSQL提交可以完全异步提交,而 MySQL的内存表不够实用(因为表锁的原因)。

    pgsql除了存储正常的数据类型外,还支持存储

    array,不管是一维数组还是数组均支持。

    json和jsonb,相比使用 text存储要高效很多。

    json和 jsonb在更高的层面上看起来几乎是一样的,但是存储实现上是不同的。

    json存储完的文本,json列会每次都解析存储的值,它不支持索引,但 可以为创建表达式索引。

    jsonb存储的二进制格式,避免了重新解析数据结构。它支持索引,这意味着 可以不使用指定索引就能查询任何路径。

    当我们比较写入数据速度时,由于数据存储 的方式的原因,jsonb会比 json 稍微的慢一点。json列会每次都 解析存储的值,这意味着键的顺序要和输入的 时候一样。但是 jsonb不同,以二进制格式存储且不保证键的顺序。因此如果有软件需要依赖键的顺序,jsonb可能不是最佳选择。使用 jsonb的优势还在于可以轻易的整合关系型数据和非关系型 数据 ,PostgreSQL对于 mongodb这类数据库是一个不小的威胁,毕竟如果一个表中只有一列数据的类型是半结构化的,没有必要为了迁就它而整个表的设计都采用 schemaless的结构。

    1. CPU

    PGSQL

    没有CPU核心数,有多少CPU核就用多少

    MySQL

    能用128核CPU,超过128核用不上

    2. 配置文件参数

    PGSQL

    一共有255个参数,用到的大概是80个,参数比较稳定,用上个大版本配置文件也可以启动当前大版本数据库

    MySQL

    一共有707个参数,用到的大概是180个,参数不断增加,就算小版本也会增加参数,大版本之间会有部分参数不兼容情况

    3. 第三方工具依赖情况

    PGSQL

    只有高可用集群需要依靠第三方中间件,例如:patroni+etcd、repmgr

    MySQL

    大部分操作都要依靠percona公司的第三方工具(percona-toolkit,XtraBackup),工具命令太多,学习成本高,高可用集群也需要第三方中间件,官方MGR集群还没成熟

    4. 高可用主从复制底层原理

    PGSQL

    物理流复制,属于物理复制,跟SQL Server镜像/AlwaysOn一样,严格一致,没有任何可能导致不一致,性能和可靠性上,物理复制完胜逻辑复制,维护简单

    MySQL

    主从复制,属于逻辑复制,(sql_log_bin、binlog_format等参数设置不正确都会导致主从不一致)

    大事务并行复制效率低,对于重要业务,需要依赖 percona-toolkit的pt-table-checksum和pt-table-sync工具定期比较和修复主从一致

    主从复制出错严重时候需要重搭主从

    MySQL的逻辑复制并不阻止两个不一致的数据库建立复制关系

    5. 从库只读状态

    PGSQL

    系统自动设置从库默认只读,不需要人工介入,维护简单

    MySQL

    从库需要手动设置参数super_read_only=on,让从库设置为只读,super_read_only参数有bug,链接:https://jiahao.baidu.com/s?id=1636644783594388753&wfr=spider&for=pc

    6. 版本分支

    PGSQL

    只有社区版,没有其他任何分支版本,PGSQL官方统一开发,统一维护,社区版有所有功能,不像SQL Server和MySQL有标准版、企业版、经典版、社区版、开发版、web版之分

    国内外还有一些基于PGSQL做二次开发的数据库厂商,例如:Enterprise DB、瀚高数据库等等,当然这些只是二次开发并不算分支

    MySQL

    由于历史原因,为三个分支版本,MariaDB分支、Percona分支 、Oracle官方分支,发展到目前为止各个分支基本互相不兼容

    Oracle官方分支还有版本之分,分为标准版、企业版、经典版、社区版

    7. SQL特性支持

    PGSQL

    SQL特性支持情况支持94种,SQL语法支持最完善,例如:支持公用表表达式(WITH查询)

    MySQL

    SQL特性支持情况支持36种,SQL语法支持比较弱,例如:不支持公用表表达式(WITH查询)

    关于SQL特性支持情况的对比,可以参考:http://www.sql-workbench.net/dbms_comparison.html

    8. 主从复制安全性

    PGSQL

    同步流复制、强同步(remote apply)、高安全,不会丢数据

    PGSQL同步流复制:所有从库宕机,主库会罢工,主库无法自动切换为异步流复制(异步模式),需要通过增加从库数量来解决,一般生产环境至少有两个从库

    手动解决:在PG主库修改参数synchronous_standby_names ='',并执行命令: pgctl reload ,把主库切换为异步模式

    主从数据完全一致是高可用切换的第一前提,所以PGSQL选择主库罢工也是可以理解

    MySQL

    增强半同步复制 ,mysql5.7版本增强半同步才能保证主从复制时候不丢数据

    mysql5.7半同步复制相关参数:

    参数rpl_semi_sync_master_wait_for_slave_count 等待至少多少个从库接收到binlog,主库才提交事务,一般设置为1,性能最高

    参数rpl_semi_sync_master_timeout 等待多少毫秒,从库无回应自动切换为异步模式,一般设置为无限大,不让主库自动切换为异步模式

    所有从库宕机,主库会罢工,因为无法收到任何从库的应答包

    手动解决:在MySQL主库修改参数rpl_semi_sync_master_wait_for_slave_count=0

    9. 多字段统计信息

    PGSQL

    支持多字段统计信息

    MySQL

    不支持多字段统计信息

    10. 索引类型

    PGSQL

    多种索引类型(btree , hash , gin , gist , sp-gist , brin , bloom , rum , zombodb , bitmap,部分索引,表达式索引)

    MySQL

    btree 索引,全文索引(低效),表达式索引(需要建虚拟列),hash 索引只在内存表

    11. 物理表连接算法

    PGSQL

    支持 nested-loop join 、hash join 、merge join

    MySQL

    只支持 nested-loop join

    12. 子查询和视图性能

    PGSQL

    子查询,视图优化,性能比较高

    MySQL

    视图谓词条件下推多,子查询上拉多

    13. 执行计划即时编译

    PGSQL

    支持 JIT 执行计划即时编译,使用LLVM编译器

    MySQL

    不支持执行计划即时编译

    14. 并行查询

    PGSQL

    并行查询(多种并行查询优化方法),并行查询一般多见于商业数据库,是重量级功能

    MySQL

    有限,只支持主键并行查询

    15. 物化视图

    PGSQL

    支持物化视图

    MySQL

    不支持物化视图

    16. 插件功能

    PGSQL

    支持插件功能,可以丰富PGSQL的功能,GIS地理插件,时序数据库插件, 向量化执行插件等等

    MySQL

    不支持插件功能

    17. check约束

    PGSQL

    支持check约束

    MySQL

    不支持check约束,可以写check约束,但存储引擎会忽略它的作用,因此check约束并不起作用(mariadb 支持)

    18. gpu 加速SQL

    PGSQL

    可以使用gpu 加速SQL的执行速度

    MySQL

    不支持gpu 加速SQL 的执行速度

    19. 数据类型

    PGSQL

    数据类型丰富,如 ltree,hstore,数组类型,ip类型,text类型,有了text类型不再需要varchar,text类型字段最大存储1GB

    MySQL

    数据类型不够丰富

    20. 跨库查询

    PGSQL

    不支持跨库查询,这个跟Oracle 12C以前一样

    MySQL

    可以跨库查询

    21. 备份还原

    PGSQL

    备份还原非常简单,时点还原操作比SQL Server还要简单,完整备份+wal归档备份(增量)

    假如有一个三节点的PGSQL主从集群,可以随便在其中一个节点做完整备份和wal归档备份

    MySQL

    备份还原相对不太简单,完整备份+binlog备份(增量)

    完整备份需要percona的XtraBackup工具做物理备份,MySQL本身不支持物理备份

    时点还原操作步骤繁琐复杂

    22. 性能视图

    PGSQL

    需要安装pg_stat_statements插件,pg_stat_statements插件提供了丰富的性能视图:如:等待事件,系统统计信息等

    不好的地方是,安装插件需要重启数据库,并且需要收集性能信息的数据库需要执行一个命令:create extension pg_stat_statements命令

    否则不会收集任何性能信息,比较麻烦

    MySQL

    自带PS库,默认很多功能没有打开,而且打开PS库的性能视图功能对性能有影响(如:内存占用导致OOM bug)

    23. 安装方式

    PGSQL

    有各个平台的包rpm包,deb包等等,相比MySQL缺少了二进制包,一般用源码编译安装,安装时间会长一些,执行命令多一些

    MySQL

    有各个平台的包rpm包,deb包等等,源码编译安装、二进制包安装,一般用二进制包安装,方便快捷

    24. DDL操作

    PGSQL

    加字段、可变长字段类型长度改大不会锁表,所有的DDL操作都不需要借助第三方工具,并且跟商业数据库一样,DDL操作可以回滚,保证事务一致性

    MySQL

    由于大部分DDL操作都会锁表,例如加字段、可变长字段类型长度改大,所以需要借助percona-toolkit里面的pt-online-schema-change工具去完成操作

    将影响减少到最低,特别是对大表进行DDL操作

    DDL操作不能回滚

    25. 大版本发布速度

    PGSQL

    PGSQL每年一个大版本发布,大版本发布的第二年就可以上生产环境,版本迭代速度很快

    PGSQL 9.6正式版推出时间:2016年

    PGSQL 10 正式版推出时间:2017年

    PGSQL 11 正式版推出时间:2018年

    PGSQL 12 正式版推出时间:2019年

    MySQL

    MySQL的大版本发布一般是2年~3年,一般大版本发布后的第二年才可以上生产环境,避免有坑,版本发布速度比较慢

    MySQL5.5正式版推出时间:2010年

    MySQL5.6正式版推出时间:2013年

    MySQL5.7正式版推出时间:2015年

    MySQL8.0正式版推出时间:2018年

    26. returning语法

    PGSQL

    支持returning语法,returning clause 支持 DML 返回 Resultset,减少一次 Client <-> DB Server 交互

    MySQL

    不支持returning语法

    27. 内部架构

    PGSQL

    多进程架构,并发连接数不能太多,跟Oracle一样,既然跟Oracle一样,那么很多优化方法也是相通的,例如:开启大页内存

    MySQL

    多线程架构,虽然多线程架构,但是官方有连接数,原因是系统的并发度是有限的,线程数太多,反而系统的处理能力下降,随着连接数上升,反而性能下降

    一般同时只能处理200 ~300个数据库连接

    28. 聚集索引

    PGSQL

    不支持聚集索引,PGSQL本身的MVCC的实现机制所导致

    MySQL

    支持聚集索引

    29. 空闲事务终结功能

    PGSQL

    通过设置 idle_in_transaction_session_timeout 参数来终止空闲事务,比如:应用代码中忘记关闭已开启的事务,PGSQL会自动查杀这种类型的会话事务

    MySQL

    不支持终止空闲事务功能

    30. 应付超大数据量

    PGSQL

    不能应付超大数据量,由于PGSQL本身的MVCC设计问题,需要垃圾回收,只能期待后面的大版本做优化

    MySQL

    不能应付超大数据量,MySQL自身架构的问题

    31. 分布式演进

    PGSQL

    HTAP数据库:cockroachDB、腾讯Tbase

    分片集群: Postgres-XC、Postgres-XL

    MySQL

    HTAP数据库:TiDB

    分片集群: 各种各样的中间件,不一一列举

    32. 数据库的文件名和命名规律

    PGSQL

    PGSQL在这方面做的比较不好,DBA不能在操作系统层面(停库状态下)看清楚数据库的文件名和命名规律,文件的数量,文件的大小

    一旦操作系统发生文件丢失或硬盘损坏,非常不利于恢复,因为连名字都不知道

    PGSQL表数据物理文件的命名/存放规律是: 在一个表空间下面,如果没有建表空间默认在默认表空间也就是base文件夹下,例如:/data/base/16454/3599

    base:默认表空间pg_default所在的物理文件夹

    16454:表所在数据库的oid

    3599:就是表对象的oid,当然,一个表的大小超出1GB之后会再生成多个物理文件,还有表的fsm文件和vm文件,所以一个大表实际会有多个物理文件

    由于PGSQL的数据文件布局内容太多,大家可以查阅相关资料

    当然这也不能全怪PGSQL,作为一个DBA,时刻做好数据库备份和容灾才是正道,做介质恢复一般是万不得已的情况下才会做

    MySQL

    数据库名就是文件夹名,数据库文件夹下就是表数据文件,但是要注意表名和数据库名不能有特殊字符或使用中文名,每个表都有对应的frm文件和ibd文件,存储元数据和表/索引数据,清晰明了,做介质恢复或者表空间传输都很方便

    33. 权限设计

    PGSQL

    PGSQL在权限设计这块是比较坑爹,抛开实例权限和表空间权限,PGSQL的权限层次有点像SQL Server,db=》schema=》object

    要说权限,这里要说一下Oracle,用Oracle来类比

    在ORACLE 12C之前,实例与数据库是一对一,也就是说一个实例只能有一个数据库,不像MySQL和SQL Server一个实例可以有多个数据库,并且可以随意跨库查询

    而PGSQL不能跨库查询的原因也是这样,PGSQL允许建多个数据库,跟ORACLE类比就是有多个实例(之前说的实例与数据库是一对一)

    一个数据库相当于一个实例,因为PGSQL允许有多个实例,所以PGSQL单实例不叫一个实例,叫集簇(cluster),集簇这个概念可以查阅PGSQL的相关资料

    PGSQL里面一个实例/数据库下面的schema相当于数据库,所以这个schema的概念对应MySQL的database

    注意点:正因为是一个数据库相当于一个实例,PGSQL允许有多个实例/数据库,所以数据库之间是互相逻辑隔离的,导致的问题是,不能一次对一个PGSQL集簇下面的所有数据库做操作

    必须要逐个逐个数据库去操作,例如上面说到的安装pg_stat_statements插件,如果您需要在PGSQL集簇下面的所有数据库都做性能收集的话,需要逐个数据库去执行加载命令

    又例如跨库查询需要dblink插件或fdw插件,两个数据库之间做查询相当于两个实例之间做查询,已经跨越了实例了,所以需要dblink插件或fdw插件,所以道理非常简单

    权限操作也是一样逐个数据库去操作,还有一个就是PGSQL虽然像SQL Server的权限层次结构db=》schema=》object,但是实际会比SQL Server要复杂一些,还有就是新建的表还要另外授权

    在PGSQL里面,角色和用户是一样的,对新手用户来说有时候会傻傻分不清,也不知道怎么去用角色,所以PGSQL在权限设计这一块确实比较坑爹

    MySQL

    使用mysql库下面的5个权限表去做权限映射,简单清晰,唯一问题是缺少权限角色

    user表

    db表

    host表

    tables_priv表

    columns_priv表

    1. 架构对比

    Mysql:多线程

    PostgreSql:多进程

    多线程架构和多进程架构之间没有绝对的好坏,例如oracle在unix上是多进程架构,在windows上是多线程架构。

    2. 对存储过程及事务的支持能力

    MySql对于无事务的MyISAM表,采用表锁定,一个长时间运行的查询很可能会长时间的阻碍,而PostgreSQL不会尊在这种问题。

    PostgreSQL支持存储过程,要比MySql好,具备本地缓存执行计划的能力。

    3. 稳定性及性能

    高并发读写,负载近极限下,PG的性能指标仍可以维持双曲线甚至对数曲线,到顶峰之后不再下降,而 MySql 明显出现一个波峰后下滑(5.5版本后Mysql企业版有优化,需要付费)

    MySql的InnoDB引擎,可以充分优化利用系统的所有内存,超大内存下PG对内存使用的不那么充分(需要根据内存情况合理分配)。

    4. 高可用

    InnoDB的基于回滚实现的 MVCC 机制,对于 PG 新老数据一起放的基于 XID 的 MVCC机制,是占优的。新老数据一起存放,需要定时触发 VACUUM,会带来多余的 IO 和数据库对象加锁开销,引起数据库整理的并发能力下降。而且 VACUUM 清理不及时,还可能会引发数据膨胀

    5. 数据同步方式:

    Mysql到现在也是异步复制,pgsql可以做到同步、异步、半同步复制。

    Mysql同步是基于binlog复制,属于逻辑复制,类似于oracle golden gate,是基于stream的复制,做到同步很困难,这种方式更加适合异步复制;

    Pgsql的同是基于wal,属于物理复制,可以做到同步复制。同时,pgsql还提供stream复制。

    Mysql的复制可以用多级从库,但是在9.2之前,PgSql不能用从库带从库。

    Pgsql的主从复制属于物理复制,相对于Mysql基于binlog的逻辑复制,数据的一致性更加可靠,复制性能更高,对主机性能的影响也更小。

    6. 权限控制对比

    MySql允许自定义一套不同的数据级、表级和列的权限,运行指定基于主机的权限

    Mysql的merge表提供了 一个独特管理多个表的方法。myisampack可以对只读表进行压缩,以后仍然可以直接访问该表中的行。

    7. SQL语句支持能力

    PG有极其强悍的 SQL 编程能力(9.x 图灵完备,支持递归!),有非常丰富的统计函数和统计语法支持,例如分析函数(Oracle的叫法,PG里叫window函数)

    支持用多种语言来写存储过程,对于R的支持也很好。这一点上Mysql就差的很远,很多分析功能都不支持。

    PgSql对表名大小写的处理,只有在Sql语句中,表明加双引号,才区分大小写。

    在Sql的标准实现上要比Mysql完善,而且功能实现比较严谨。

    对表连接支持比较完整,优化器的功能比较完整,支持的索引类型很多,复杂查询能力较强。

    Mysql采用索引组织表,这种存储方式非常适合基于主键匹配的查询、删改操作,但是对表结果设计存在约束;

    Mysql的Join操作的性能非常的差,只支持Nest Join,所以一旦数据量大,性能就非常的差。PostgresSQL除了支持 Nest Join 和 Sort Merge Join,PostgreSQL还支持正则表达式查询,MySql不支持。

    8. 数据类型支持能力

    PostgreSQL可以更方便的使用UDF(用户定义函数)进行扩展。

    有丰富的几何类型,实际上不止集合类型,PG有大量的字典、数组、bitmap等数据类型,因此PG多年来在 GIS 领域处于优势地位。相比之下Mysql就差很多,就是因为PG的空间数据扩展 PostGIS远远强于 MySql的 my spatial 而采用 PgSql的。Mysql中的空间数据类型有4种,分别是 CEOMETRY、POINT、LINESTRING、POLYGON,其空间索引只能在存储引擎为 MyiSam的表中创建,用SPATIAL关键字进行扩展,使得能够用于创建正规索引类型的语法创建空间索引。创建空间索引的列,必须将其声明为NOT NULL。不同的存储亲情有差别。MyISAM和InnoDB 都支持 spatial extensions,但差别在于:如果使用MyISAM,可以建立 spatial index,而 InnoDB是不支持的。

    pgsql对json支持比较好,还有很逆天的fdw功能,就是把别的数据库中的表当自己的用。

    pgsql的字段类型支持的多,有很多mysql没有的类型,但是实际中有时候用到。

    一半关系型数据库的字符串长度8k左右,无限长的 TEXT 类型的功能受限,只能作为外部带数据访问。而 PG 的 TEXT 类型可以直接访问,SQL 语法内置正则表达式,可以索引,还可以全文检索,或使用 xml xpath。用 PG 的话,文档数据库都可以省了。

    postgresql 有函数,用于报表、统计很方便

    PG支持 R-Trees这样可扩展的索引类型,可以方便的处理一些特殊数据。

    PG可以使用函数和条件所以,使得数据库的调优非常灵活,mysql就没有这个功能,条件索引在web应用中很重要。

    9. 如可过程容错能力

    大批量数据入库,PostgreSql要求所有的数据必须完全满足要求,有一条错误,整个数据入库过程失败。MySql无此问题。

    10. 表组织方式

    pgsql用继承的方式实现分区表,让分区表的使用不方便且性能差,这点比不上mysql。

    pg主表采用堆表存放,MySQL采用索引组织表,能够支持比MySql更大的数据量。

    MySql分区表的实现要优于PG的基于继承表的分区实现,主要体现在分区个数达到成千上万后的处理性能差异很大。

    11. 开发结构

    对于web应用来所,mysql 5.6 的内置 MC API 功能很好用,PgSQL差一些。

    PG的“无锁定”特性非常突出,甚至包括 vacuum 这样的整理数据空间的操作,这个和 PGSQL的 MVCC 实现有关系。

    好文要顶 关注我 收藏该文  

    茄子777

    粉丝 - 0 关注 - 0

    +加关注

    00

    « 上一篇: 多线程中的wait与join

    » 下一篇: 负载均衡相关

    posted @ 2022-11-02 16:20 茄子777 阅读(55) 评论(0) 编辑 收藏 举报

    刷新评论刷新页面返回顶部

    登录后才能查看或发表评论,立即 登录 或者 逛逛 博客园首页

    【推荐】阿里云新人特惠,爆款云服务器2核4G低至0.46元/天

    【推荐】双十一同价!腾讯云云服务器抢先购,低至4.2元/月

    编辑推荐:

    · 一个有趣的 nginx HTTP 400 响应问题分析

    · 谁说.NET没有GC调优?只改一行代码就让程序不再占用内存

    · 为什么标准库的模板变量都是 inline 的

    · .net 如何优雅的使用 EFCore

    · 在 C# 中使用 Halcon 开发视觉检测程序

    阅读排行:

    · Entity Framework Core 7中高效地进行批量数据插入

    · 除了 filter 还有什么置灰网站的方式?

    · 快速绘制流程图「GitHub 热点速览 v.22.47」

    · 使用.NET7和C#11打造最快的序列化程序-以MemoryPack为例

    · 私藏!资深数据专家SQL效率优化技巧 ⛵

    显示全文