mysql命令行下怎样实现数据的回滚操作

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql命令行下怎样实现数据的回滚操作相关的知识,希望对你有一定的参考价值。

当启动Binlog后,事务会产生Binlog Event,这些Event被看做事务数据的一部分。因此要保证事务的Binlog Event和InnoDB引擎中的数据的一致性。所以带Binlog的CrashSafe要求mysql宕机重启后能够保证:

- 所有已经提交的事务的数据仍然存在。

- 所有没有提交的事务的数据自动回滚。

- 所有已经提交了的事务的Binlog Event也仍然存在。

- 所有没有提交事务没有记录Binlog Event。

这些要求很好理解,如果重启后数据还在,但是Binlog Event没有了,就没办法复制到其他节点上了。如果重启后,数据没了,但是Binlog Event还在,那么不存在的数据就会被复制到其他节点上,从而导致主从的不一致。

为了保证带Binlog的CrashSafe,MySQL内部使用的两阶段提交(Two Phase Commit)。

2 - MySQL的Two Phase Commit(2PC)

在开启Binlog后,MySQL内部会自动将普通事务当做一个XA事务来处理:
- 自动为每个事务分配一个唯一的ID
- COMMIT会被自动的分成Prepare和Commit两个阶段。
- Binlog会被当做事务协调者(Transaction Coordinator),Binlog Event会被当做协调者日志。
想了解2PC,可以参考文档:【https://en.wikipedia.org/wiki/Two-phase_commit_protocol。】

- 分布式事务ID(XID)

使用2PC时,MySQL会自动的为每一个事务分配一个ID,叫XID。XID是唯一的,每个事务的XID都不相同。XID会分别被Binlog和InnoDB记入日志中,供恢复时使用。MySQ内部的XID由三部分组成:

- 前缀部分

前缀部分是字符串"MySQLXid"

- Server ID部分

当前MySQL的server_id
- query_id部分

为了保证XID的的唯一性,数字部分使用了query_id。MySQL内部会自动的为每一个语句分配一个query_id,全局唯一。

参考代码:sql/xa。h的struct xid_t结构。

- 事务的协调者Binlog

Binlog在2PC中充当了事务的协调者(Transaction Coordinator)。由Binlog来通知InnoDB引擎来执行prepare,commit或者rollback的步骤。事务提交的整个过程如下:

1. 协调者准备阶段(Prepare Phase)

告诉引擎做Prepare,InnoDB更改事务状态,并将Redo Log刷入磁盘。

2. 协调者提交阶段(Commit Phase)

2.1 记录协调者日志,即Binlog日志。

2.2 告诉引擎做commit。
注意:记录Binlog是在InnoDB引擎Prepare(即Redo Log写入磁盘)之后,这点至关重要。

在MySQ的代码中将协调者叫做tc_log。在MySQL启动时,tc_log将被初始化为mysql_bin_log对象。参考sql/binlog.cc中的init_server_components():
if (opt_bin_log) tc_log= &mysql_bin_log;

而在事务提交时,会依次执行:
tc_log->prepare();
tc_log->commit();
参考代码:sql/binlog.cc中的ha_commit_trans()。当mysql_bin_log是tc_log时,prepare和commit的代码在sql/binlog.cc中:

MYSQL_BIN_LOG::prepare();
MYSQL_BIN_LOG::commit();

-协调者日志Xid_log_event
作为协调者,Binlog需要将事务的XID记入日志,供恢复时使用。Xid_log_event有以下几个特点:
- 仅记录query_id
因为前缀部分不变,server_id已经记录在Event Header中,Xid_log_event中只记录query_id部分。
- 标志事务的结束

在Binlog中相当于一个事务的COMMIT语句。

一个事务在Binlog中看起来时这样的:
Query_log_event("BEGIN");DML产生的events; Xid_log_event;

- DDL没有BEGIN,也没有Xid_log_event 。
- 仅InnoDB的DML会产生Xid_log_event
因为MyISAM不支持2PC所以不能用Xid_log_event ,但会有COMMIT Event。
Query_log_event("BEGIN");DML产生的events;Query_log_event("COMMIT");

问题:Query_log_event("COMMIT")和Xid_log_event 有不同的影响吗?

- Xid_log_event 中的Xid可以帮助master实现CrashSafe。
- Slave的CrashSafe不依赖Xid_log_event
事务在Slave上重做时,会重新产生XID。所以Slave服务器的CrashSafe并不依赖于Xid_log_event 。Xid_log_event 和Query_log_event("COMMIT"),只是作为事务的结尾,告诉Slave Applier去提交这个事务。因此二者在Slave上的影响是一样的。

3 - 恢复(Recovery)
这个机制是如何保证MySQL的CrashSafe的呢,我们来分析一下。这里我们假设用户设置了以下参数来保证可靠性:

- 恢复前事务的状态
在恢复开始前事务有以下几种状态:
- InnoDB中已经提交
根据前面2PC的过程,可知Binlog中也一定记录了该事务的的Events。所以这种事务是一致的不需要处理。
- InnoDB中是prepared状态,Binlog中有该事务的Events。
需要通知InnoDB提交这些事务。
- InnoDB中是prepared状态,Binlog中没有该事务的Events。
因为Binlog还没记录,需要通知InnoDB回滚这些事务。
- Before InnoDB Prepare
事务可能还没执行完,因此InnoDB中的状态还没有prepare。根据2PC的过程,Binlog中也没有该事务的events。 需要通知InnoDB回滚这些事务。

- 恢复过程
从上面的事务状态可以看出:恢复时事务要提交还是回滚,是由Binlog来决定的。
- 事务的Xid_log_event 存在,就要提交。
- 事务的Xid_log_event 不存在,就要回滚。

恢复的过程非常简单:
- 从Binlog中读出所有的Xid_log_event
- 告诉InnoDB提交这些XID的事务
- InnoDB回滚其它的事务
参考技术A mysql命令行下怎样实现数据的回滚操作
在MySQL有时执行了错误的update或者delete时导致大量数据错误恢复的办法。执行时没有开启事务,也没有对数据进行。这时就需要使用到sqlbinlog工具。
sqlbinlog需要开启,具体的打开方法就不说了。

使用sqlbinlog会产生bin文件,恢复就需要用到这些文件。文件中记录着数据库的所有操作。(此方法的操作是将数据库之前所执行的语句重新执行一次,以达到恢复效果)
具体步骤:1,先找到bin文件,一般都是在mysql的data文件夹中,结尾以.00000X等形式结束。
2,寻找需要还原的时间点 使用语句 mysqlbinlog 文件名 例(MySQLbinlog xxbin.000001)来查看内容,然后找到对应的具体时间
3,导出sql语句,使用语句 mysqlbinlog 文件名>sql文件路径 例(mysqlbinlog xxxbin,00001>>a.sql | mysql -u root -p )
如果需要指定时间导出--start--date -stop='' --date='' 来导出指定时间执行的语句例(sqlbinlog --start-stop='2015-11-22 10:00:00' xxbin.000001>a.sql | mysql -u root -p )这句意思是导出在2015-11-22 10点之前的语句,反之start是导出时间之后的。 start和stop可以同时使用。
如果存在多个bin文件,则按照需要导出。
4,使用mysql将导出的语句执行一次。本回答被提问者采纳

mysql数据库事务的回滚操作

事务的基本概念:如果一个包含多个步骤业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败。

mysql数据库中事务默认自动提交
事务提交两种方式:
自动提交:一条DML(增删改)语句会自动提交一次事务
手动提交:需要开启事务,在提交

修改事务默认提交方式,查看当前默认提交方式
SELECT @@autocommit --1代表自动提交,0代表手动提交
set @@autocommit=0 --设置提交方式

操作:
1开启事务:statrt transaction
2回滚:rollback
3提交:commit

事务四大特征:
1原子性,不可分割最小操作单位,要不同时失败,成功
2持久性,事务提交,数据库持久保存
3隔离性,多个事务之间相互影响独立
4一致性,事务操作前后数据总量不变

事务的隔离级别:多个事务之间是隔离独立的,但是如果多个事务操作数据,会出现问题,存在隔离级别:
1脏读:一个事务,读取到另一个没有提交的数据
2不可重复读(虚读):在同一个事务中,两次读取到数据不一样
3幻读:一个事务操作DML数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改
隔离级别:
1read uncommitted:读未提交,会发生脏读、虚读、幻读
2read committed:读已提交,会产生虚读、幻读(Oracle默认级别)
3repeatable read: 可重复读(mysql默认级别)
4serializable:串行化 解决所有问题
安全级别越来越高,但效率越来越低
数据库查看、设置级别
select @@tx_isolation;
set global transaction isolation level 级别字符串

sql分类:
1DDL:操作数据库和表
2DML:增删改表中数据
3DQL:查询表中数据
4DCL:管理用户授权
添加用户
use mysql
语法:create USER ‘账号’@‘主机名’ IDENTIFIED By ‘密码’
CREATE USER ‘ancen’@‘127.0.0.1’ IDENTIFIED By ‘aaa’
删除用户
DROP USER ‘用户’@‘主机名’
修改用户

DBA:数据库管理员

查询权限
SHOW GRANTS FOR ‘用户名’@‘主机’;
SHOW GRANTS FOR ‘root’@‘localhost’;

授予权限
GRANT 权限列表 ON 数据库名.表名 to ‘用户’@‘主机’
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE ON app.admin to ‘ancen’@‘127.0.0.1’

GRANT ALL ON app.* to ‘ancen’@‘127.0.0.1’

撤销权限
revoke 权限列表 on 数据库.表名 from ‘ancen’@‘127.0.0.1’

以上是关于mysql命令行下怎样实现数据的回滚操作的主要内容,如果未能解决你的问题,请参考以下文章

2020-12-15:mysql的回滚机制是怎么实现的?

mysql数据库事务的回滚操作

如果实现oracle中DDL语句的回滚

浅谈Mysql数据库事物及数据库引擎

浅谈Mysql数据库事物及数据库引擎

命令行下操作MySQL数据库,各种命令的使用入门示例。(附图)