【mysql】主从同步,事务等概念

时间:2023-12-10 12:16:32

问题:

mysql用binary log来保证主从同步的可靠性和安全性,在mysql中,主从同步是异步线程和异步任务来保证的。

(在这点上,其它存储引擎有另外的选项,比如mongoDB和ElasticSearch的核心存储可以执行同步选项。mongoDB甚至支持同步到所有的从库后返回值,这样能够保证主从同步是没有延迟的。)

回到mysql,binary log是如何生成的?哪些操作会记录,哪些操作不会记录?

比如我有个疑问就是,对于事务操作,mysql是如何记录binary log的呢?

这个需要参考文档1:mysql在事务中的同步原理。

我来做个翻译:

先了解下,一个事务中可能包含transactional和nontransactional statement,这两个的区别是什么呢?

transactional statement是指,在事务处理失败,并执行rollback该事务时,该语句会自动回滚,这个是由mysql来保证的;

nontranscational statement是指,在事务处理失败,并执行rollback该事务时,该语句不会自动回滚,需要上层应用,即程序猿来保证。

mysql处理事务语句时遵循两条规则:

规则1:如果该事务的初始化语句是nontransactional语句,会立即写入到binlog中。其它事务语句会被cached。如果事务的结果是commit,那么在事务commit之后,这些cached语句会写入到binlog(之前是不写入的);但是如果事务回滚,有些cached语句仍然会被写入到binlog中,如果这些语句是nontransactional语句(因为这些语句是无法rollback的),其它会被抛弃;

规则2:基于statement的日志,nontransactional语句受系统参数影响(具体是:binlog_direct_non_transactional_updates)。如果该参数为OFF(默认值),日志是不会记录的。如果该参数为ON,nontransactional语句执行后会立即记入日志(而不仅仅是initial nontransactional语句)。其它语句会被保持在transaction缓存中,事务提交后记录日志。binlog_direct_non_transactional_updates对日志记录没有影响,在row-format(基于行)或者mixed-format(混合型日志)的binlog处理中。

我们来对mysql的语句做下区分:

Transactional语句:仅仅操作transactional tables的语句;

Nontransactional语句:仅仅操作nontransactional tables的语句;

Mixed语句:同时会操作nontransactional和transactional tables的语句;

在执行以下任一动作是,Mixed语句(更新一个transactional table)被认为是不安全的:

1,更新或读取临时表(temporary table);

2,读取untransactional table,并且事务的隔离级别是小于 DEPEATABLE_READ(the transaction isolation level is less than DEPEATABLE_READ);

一个事务中,如果一个mixed语句紧跟着要更新transactional table,并且它要执行以下任一操作时,被认为是不安全的:

1,更新任一tabe,and 从临时表中读取;

2,更新任一nontransactional table,并且binlog_direct_non_transactional_updates为OFF;

如果事务之间混合更新transactional 和 nontransactional表,binlog中的语句顺讯是正确的,并且所有已执行的语句被记录在binlog中,即使最后事务被rollback。

然而,如果第一个连接处理的transaction没有执行完毕,此时第二个连接更新的是nontransactional table,语句记录在binlog的顺序是非有序的。原因是,第二个连接执行的更新语句会在执行更新后立即写入到binlog中,而不管第一个连接的执行情况如何。

这里有我个人理解是,第一个连接在处理一个事务,现在进来一个新的连接(connection 2),connection2执行的语句是nontransactional 语句,此时有些观点会认为connection1的语句先记录在binlog中,connection2的语句后被记录在binlog中,但实际情况不是。

如果从库的引擎是nontransactional,主库的事务执行transactional和nontransactional表更新时应当要避免的,因为这会造成数据的不一样(具体指主库的transactional表和从库的nontransactional表)。

每一个事务都会被记录在binlog中,只要是以start开始,commit或者rollback结束。这个对于使用nontransactional存储引擎(比如MyISAM)的表操作语句也同样适用。

要了解什么样的table是transactional table,设么样的table是nontransactional table?参考文档2

参考文档1:https://dev.mysql.com/doc/refman/5.7/en/replication-features-transactions.html

文档2:https://dev.mysql.com/doc/refman/5.7/en/nontransactional-tables.html