redis┃面试官问我redis事务和mysql事务的区别,我

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis┃面试官问我redis事务和mysql事务的区别,我相关的知识,希望对你有一定的参考价值。

参考技术A 1、前言

面试官:我看你简历上写了熟悉redis,看来工作中用的很多吧?

我:是的,我们项目中经常用到redis(来,随便问,看我分分钟秒杀你)

面试官:那你给我说说redis的事务和mysql的事务有什么区别吧

我:额。。。事务还有区别????

面试官:比如说redis的事务是不支持原子性和持久性的,包括他们的实现原理等方面也是有很大区别的。

我:学到了。。。。。。

2、正文

事务的四大特性

ACID,指数据库事务正确执行的四个基本要素的缩写。包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。

说的是一个事物内所有操作就是最小的一个操作单元,要么全部成功,要么全部失败。这是最基本的特性,保证了因为一些其他因素导致数据库异常,或者宕机。

一个事务可以封装状态改变(除非它是一个只读的)。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。

一致性有下面特点:

在现实中,事务系统遭遇并发请求时,这种串行化是有成本的, Amdahl法则描述如下:它是描述序列串行执行和并发之间的关系。

“一个程序在并行计算情况下使用多个处理器所能提升的速度是由这个程序中串行执行部分的时间决定的。”

大多数数据库管理系统选择(默认情况下)是放宽一致性,以达到更好的并发性。

事物的隔离性,基于原子性和一致性,因为事物是原子化,量子化的,所以,事物可以有多个原子包的形式并发执行,但是,每个事物互不干扰。

但是,由于多个事物可能操作同一个资源,不同的事物为了保证隔离性,会有很多锁方案,当然这是数据库的实现,他们怎么实现的,我们不必深究。

持久性,当一个事物提交之后,数据库状态永远的发生了改变,即这个事物只要提交了,哪怕提交后宕机,他也确确实实的提交了,不会出现因为刚刚宕机了而让提交不生效,是要事物提交,他就像洗不掉的纹身,永远的固化了,除非你毁了硬盘。

事务命令

mysql:

Begin:显式的开启一个事务

Commit:提交事务,将对数据库进行的所有的修改变成永久性

Rollback:结束用户的事务,并撤销现在正在进行的未提交的修改

redis:

Multi:标记事务的开始

Exec:执行事务的commands队列

Discard:结束事务,并清除commands队列

默认状态

mysql:

mysql会默认开启一个事务,且缺省设置是自动提交,即每成功执行sql,一个事务就会马上commit,所以不能rollback,

redis:

redis默认不会开启事务,即command会立即执行,而不会排队,并不支持rollback

使用方式

mysql(包含两种方式):

用Begin、Rollback、commit显式开启并控制一个 新的 Transaction

执行命令 set autocommit=0,用来禁止当前会话自动commit,控制 默认开启的事务

redis:

用multi、exec、discard,显式开启并控制一个Transaction。

(注意:这里没有强调 “新的” ,因为默认是不会开启事务的)。

实现原理

mysql:

mysql实现事务,是基于undo/redo日志

undo记录修改前状态,rollback基于undo日志实现

redo记录修改后的状态,commit基于redo日志实现

既然是基于redo日志实现记录修改后的状态,那么大家应该也知道,redo日志是innodb专有的,所以innodb会支持事务

在mysql中无论是否开启事务,sql都会被立即执行并返回执行结果,只是事务开启后执行后的状态只是记录在redo日志,执行commit之后,数据才会被写入磁盘

(以上内容后面我会详细在mysql篇给大家讲到,大家可以先简单了解下)

所以,上述代码,insertSelective 将会被立即赋值(无论是否开启事务,只是结果或未被写入磁盘):

redis:

redis实现事务,是基于commands队列

如果没有开启事务,command将会被立即执行并返回执行结果,并且直接写入磁盘

如果事务开启,command不会被立即执行,而是排入队列,并返回排队状态(具体依赖于客户端(例如:spring-data-redis)自身实现)。

调用exec才会执行commands队列

以上代码如果没有开启事务,操作被立即执行,a将会被立即赋值(true/false)

如果开启事务,操作不会被立即执行,将会返回null值,而a的类型是boolean,所以将会抛出异常:

Redis事务不支持Rollback(重点)

事实上Redis命令在事务执行时可能会失败,但仍会继续执行剩余命令而不是Rollback(事务回滚)。如果你使用过关系数据库,这种情况可能会让你感到很奇怪。然而针对这种情况具备很好的解释:

redis 事务中的错误

事务期间,可能会遇到两种命令错误:

客户端会在EXEC调用之前检测第一种错误。 通过检查排队命令的状态回复(***注意:这里是指排队的状态回复,而不是执行结果***),如果命令使用QUEUED进行响应,则它已正确排队,否则Redis将返回错误。如果排队命令时发生错误,大多数客户端将中止该事务并清除命令队列。然而:

这是由于INCR命令的语法错误,将在调用EXEC之前被检测出来,并终止事务(version2.6.5+)。

EXEC命令执行之后发生的错误并不会被特殊对待:即使事务中的某些命令执行失败,其他命令仍会被正常执行。

## 分布式事务面试官问我:MySQL中的XA事务崩溃了如何恢复??

写在前面

前段时间搭建了一套MySQL分布式数据库集群,数据库节点有12个,用来测试各种分布式事务方案的性能和优缺点。测试MySQL XA事务时,正当测试脚本向数据库中批量插入数据时,强制服务器断电!注意:是直接拔电源,使其瞬间断电,再次重启服务器后,MySQL数据库报错了。特此记录MySQL XA事务的恢复。

MySQL XA事务问题

服务器强制断电后重启,此时MySQL报错,查看MySQL启动日志时,发现如下所示的错误信息。

InnoDB: The log sequence number in ibdata files does not match
InnoDB: the log sequence number in the ib_logfiles!
100224 23:24:20 InnoDB: Database was not shut down normally!
InnoDB: Starting crash recovery.
InnoDB: Reading tablespace information from the .ibd files...
InnoDB: Restoring possible half-written data pages from the doublewrite
InnoDB: buffer...
InnoDB: Transaction 0 4497755 was in the XA prepared state.
InnoDB: Transaction 0 4468551 was in the XA prepared state.
InnoDB: Transaction 0 4468140 was in the XA prepared state.
InnoDB: 3 transaction(s) which must be rolled back or cleaned up
InnoDB: in total 0 row operations to undo
InnoDB: Trx id counter is 0 5312768
InnoDB: Starting in background the rollback of uncommitted transactions
100224 23:24:20 InnoDB: Rollback of non-prepared transactions completed
100224 23:24:20 InnoDB: Started; log sequence number 0 3805002509
100224 23:24:20 InnoDB: Starting recovery for XA transactions...
100224 23:24:20 InnoDB: Transaction 0 4497755 in prepared state after recovery
100224 23:24:20 InnoDB: Transaction contains changes to 8 rows
100224 23:24:20 InnoDB: Transaction 0 4468551 in prepared state after recovery
100224 23:24:20 InnoDB: Transaction contains changes to 1 rows
100224 23:24:20 InnoDB: Transaction 0 4468140 in prepared state after recovery
100224 23:24:20 InnoDB: Transaction contains changes to 1 rows
100224 23:24:20 InnoDB: 3 transactions in prepared state after recovery
100224 23:24:20 [Note] Found 3 prepared transaction(s) in InnoDB
100224 23:24:20 [Warning] Found 3 prepared XA transactions
100224 23:24:20 [Note] Event Scheduler: Loaded 0 events
100224 23:24:20 [Note] /opt/mysql/bin/mysqld: ready for connections.
Version: ‘8.0.18‘ socket: ‘/tmp/mysql.sock‘ port: 3306 MySQL Community Server (GPL) 

从上面的日志信息中,可以看出有三个XA的事务没有提交或回滚。那该如何恢复MySQL的XA事务呢?

恢复MySQL XA事务

首先,登录到MySQL,执行如下命令。

mysql> xa recover;
+----------+--------------+--------------+------------------------------------------------------------+
| formatID | gtrid_length | bqual_length | data |
+----------+--------------+--------------+------------------------------------------------------------+
| 131075 | 30 | 28 | 1-7f000001:bae5:4b6928eb:f06397f000001:bae5:4b6928eb:f0650 |
| 131075 | 30 | 28 | 1-7f000001:bae5:4b6928eb:fb5c37f000001:bae5:4b6928eb:fb5cd |
| 131075 | 30 | 28 | 1-7f000001:bae5:4b6928eb:f03ea7f000001:bae5:4b6928eb:f0400 |
+----------+--------------+--------------+------------------------------------------------------------+ 

数据表示信息如下:

formatIDis the formatIDpart of the transaction xid
gtrid_lengthis the length in bytes of the gtridpart of the xid
bqual_lengthis the length in bytes of the bqualpart of the xid
datais the concatenation of the gtridand bqualparts of the xid 

这是三个XA事务的信息,准备直接回滚。

mysql> xa rollback ‘1-7f000001:bae5:4b6928eb:fb5c3‘,‘7f000001:bae5:4b6928eb:fb5cd‘,131075;
Query OK, 0 rows affected (0.41 sec) 

MySQL XA事务补充

XA事务支持限于InnoDB存储引擎。

MySQL XA实施是针对外部XA的,其中,MySQL服务器作为资源管理器,而客户端程序作为事务管理器。未实施“内部XA”。这样,就允许MySQL服务器内的单独存储引擎作为RM(资源管理器),而服务器本身作为TM(事务管理器)。处理包含1个以上存储引擎的XA事务时,需要内部XA。内部XA的实施是不完整的,这是因为,它要求存储引擎在表处理程序层面上支持两阶段提交,目前仅对InnoDB实现了该特性。

对于XA START,不支持JOIN和RESUME子句。

对于XA END,不支持SUSPEND [FOR MIGRATE]子句。

在全局事务内,对于每个XA事务,xid值的bqual部分应是不同的,该要求是对当前MySQL XA实施的限制。它不是XA规范的组成部分。

如果XA事务达到PREPARED状态而且MySQL服务器宕机,当服务器重启后,能够继续处理事务。就像原本应当的那样。但是,如果客户端连接中止而服务器继续运行,服务器将回滚任何未完成的XA事务,即使该事务已达到PREPARED状态也同样。它应能提交或回滚PREPARED XA事务,但在不更改二进制日志机制的情况下不能这样。

重磅福利

微信搜一搜【冰河技术】微信公众号,关注这个有深度的程序员,每天阅读超硬核技术干货,公众号内回复【PDF】有我准备的一线大厂面试资料和我原创的超硬核PDF技术文档,以及我为大家精心准备的多套简历模板(不断更新中),希望大家都能找到心仪的工作,学习是一条时而郁郁寡欢,时而开怀大笑的路,加油。如果你通过努力成功进入到了心仪的公司,一定不要懈怠放松,职场成长和新技术学习一样,不进则退。如果有幸我们江湖再见!

另外,我开源的各个PDF,后续我都会持续更新和维护,感谢大家长期以来对冰河的支持!!

以上是关于redis┃面试官问我redis事务和mysql事务的区别,我的主要内容,如果未能解决你的问题,请参考以下文章

京东面试官问我:“聊聊MySql事务,MVCC?”

面试官问:Redis的操作如何与数据库事务保持一致

面试官问我MySQL如何保证数据的可靠性,被虐的体无完肤

京东面试官:Redis 这些我必问

面经面试官问我:数据库中事务的隔离级别有哪些?各自有什么特点?然而。。。

面试官问我谈谈对事务隔离机制的理解?我是这样回答的