后端面经系列-事务提交了,你的数据就一定不会丢吗?

后端面经系列-事务提交了,你的数据就一定不会丢吗?

August 21, 2023
后端开发, 数据库
Mysql, 数据库, 事务

什么是undo log?为什么需要undo log? #

undo log,又称回滚日志。undo log有以下作用:

  • 事务回滚。为了保证事务的原子性,事务中的操作要么全部完成,要么什么也不做。如果事务执行到一半出现了错误,那么就需要回滚到事务开始之前的状态,我们就必须要记录事务开始执行时的状态, 准确的说是相关记录在那个时刻的数据版本。
  • mvcc。同一条记录的不同版本的undo log,通过roll pointer串联成了一个版本链。mvcc,即多版本并发控制,就是通过这个版本链来实现的。

什么是redo log?为什么需要redo log? #

又称 重做日志。 redo log主要用于崩溃恢复,保证事务的持久性。

什么是binlog?它有几种模式?用来做什么? #

binlog是binary log,即二进制日志,它记录了数据库发生的变化,如表结构、表中数据发生的变化。 binlog的作用:

  • 复制。单台服务器性能有限,为了提高性能,可能会采用一主多从的模式,这时候就需要binlog来记录主库的变化,然后从库通过读取binlog来同步主库的变化。
  • 恢复。如果数据库发生了错误,或者误操作,我们可以通过全量备份+增量binlog的方式来恢复数据库。

binlog的模式(应该说binlog的日志文件格式更合适一些):

  • statement 基于语句,binglog中会记录实际执行的语句。同一条sql语句,在不同的数据库中可能会有不同的执行结果,所以这种模式可能会导致主从不一致。
  • row 基于行,binlog中会记录每一行数据的变化。
  • mixed 混合模式。

事务是如何执行的? #

什么是ACID?隔离性和隔离级别是什么关系?你觉得哪个隔离级别满足这里的隔离性要求? #

ACID:

  • A atomic,原子性。
  • C consistency,一致性。
  • I isolation,隔离性。
  • D durability,持久性。

不同的隔离级别,实现的隔离性不同。读未提交,隔离性最差,串行化,隔离性最好。

根据实际情况回答。

redo log的刷盘时机有哪些?该如何选择?你们公司用的哪个配置?为什么用这个配置? #

刷盘时机:

  • innodb_flush_log_at_trx_commit = 0,每隔1s写入到日志,并刷盘。可能丢失1s的数据。
  • innodb_flush_log_at_trx_commit = 1,每次事务提交时写日志,并刷盘。
  • innodb_flush_log_at_trx_commit = 2,每次事务提交时将写日志,每秒刷盘。

查看配置:

show variables like 'innodb_flush_log%';
``

查看 innodb_flush_log_at_trx_commit 配置的值:


如何选择:
根据对性能和数据安全性的要求来选择。


根据实际情况回答:
- 对数据安全性要求高,设置为1。
- 数据安全性和性能之间做一个权衡,设置为2。
- 对性能要求高,对数据安全性要求不高,设置为0。

## binlog的刷盘时机有哪些?该如何选择?你们公司用的哪个配置?为什么用这个配置?
binlog的刷盘时机由参数sync_binlog控制,有以下几种模式:
- sync_binlog=0,每次事务提交时写入,但不主动刷盘。
- sync_binlog=1,每次事务提交时写入,并刷盘。
- sync_binlog=N,每次事务提交时写入,每N次提交刷盘一次。

如何选择,根据对性能和数据安全性的要求来选择。

## 我的事务提交了,就一定不会丢吗?怎么确保一定不会丢?
不一定。

最安全的做法是:
设置innodb_flush_log_at_trx_commit=1,sync_binlog=1,即每次提交事务时,redo log和binlog都同步刷盘,这样就可以保证事务提交后,数据一定不会丢失。

## 什么是page cache?为什么不直接写到磁盘?
page cache 是页缓存,是内存中的一块区域,用来缓存磁盘中的数据,加速cpu对磁盘的访问。
cpu写入磁盘的时候,先写入到page cache;再读取文件内容时,如过内容已经存在于page cache中,则直接从page cache中读取。

不直接写到磁盘,是应为磁盘的写入速度和内存的写入速度差别很大。


## 在分布式环境下,当服务器告诉我写入成功的时候,一定写入成功了吗?如果服务器宕机了可能发生什么?
这个要看服务器的主从同步模式,如果是异步复制,那么写入成功后,主库宕机,可能会丢失数据。

以mysql为例,mysql的主从同步策略有以下几种:
- 异步复制。主库写入成功后,立即返回成功,不等待从库同步。这种情况下,如果主库宕机,可能会丢失数据。
- 半同步复制。主库写入成功后,等待至少x个(可设置)从库写入成功后,才返回成功。
- 全同步复制。主库写入成功后,等待所有从库写入成功后,才返回成功。

可以通过以下命令来查看相关参数:
···sql
show variables like '%sync_master%';