深入浅析MySQL数据库当中的undo日志
更新时间:2023-11-25第一段:undo日志简介
MySQL的InnoDB引擎实现了事务。在进行CRUD操作时,InnoDB引擎会自动地记录数据修改,如INSERT,UPDATE,DELETE操作在undo日志文件中。如果发生回滚,undo log文件中的记录将会撤销先前提交的操作。
undo日志是事务处理中的一项关键功能,并且是InnoDB引擎ACID事务的特性之一。undo日志跟踪了引擎的修改操作,因此可以在需要时撤销这些操作。
mysql> create table test(id int, name varchar(10)) engine=InnoDB;
Query OK, 0 rows affected (0.03 sec)
mysql> insert into test values(1, 'Ashely'), (2, 'Bob'), (3, 'Charlie');
Query OK, 3 rows affected (0.01 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update test set name='David' where id=1;
Query OK, 1 row affected (0.01 sec)
mysql> update test set name='Eric' where id=2;
Query OK, 1 row affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from test;
+------+-------+
| id | name |
+------+-------+
| 1 | David |
| 2 | Eric |
| 3 | Charlie |
+------+-------+
3 rows in set (0.00 sec)
第二段:undo日志的作用
在以上的示例中,undo日志将最初插入到表test中的行保持在同一状态,即InnoDB引擎使第一个操作的结果不可见。第二个操作修改了行2的数据。因此,undo log跟踪了此更新操作的更改,并确保后续的操作不会增加其影响范围。如果我们现在回滚第三个操作─更新行1的数据,undo日志中记录的更改将撤销Everything After此更新中发生的任何变化。你现在可以看到,这就是为什么undo日志既重要又必要的原因。
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update test set name='Edward' where id=3;
Query OK, 1 row affected (0.00 sec)
mysql> select * from test;
+------+-------+
| id | name |
+------+-------+
| 1 | David |
| 2 | Eric |
| 3 | Edward |
+------+-------+
3 rows in set (0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test;
+------+-------+
| id | name |
+------+-------+
| 1 | David |
| 2 | Eric |
| 3 | Charlie |
+------+-------+
3 rows in set (0.00 sec)
第三段:undo日志和MVCC
多版本并发控制,即MVCC,是一个允许多个同时进行的事务操作,允许在同一时间并行的处理读写操作的技术。undo日志和MVCC标准实现一起使用将实现并发控制。该技术的一个示例是在应用程序中看不到未提交的事务的存在 - 此时可以将每个事务的快照保存为数据库的一部分。
mysql> select * from test;
+------+-------+
| id | name |
+------+-------+
| 1 | David |
| 2 | Eric |
| 3 | Charlie |
+------+-------+
3 rows in set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update test set name='Frank' where id=1;
Query OK, 1 row affected (0.00 sec)
mysql> select * from test;
+------+--------+
| id | name |
+------+--------+
| 1 | Frank |
| 2 | Eric |
| 3 | Charlie |
+------+--------+
3 rows in set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> delete from test where id=3;
Query OK, 1 row affected (0.00 sec)
mysql> select * from test;
+------+-------+
| id | name |
+------+-------+
| 1 | Frank |
| 2 | Eric |
+------+-------+
2 rows in set (0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test;
+------+--------+
| id | name |
+------+--------+
| 1 | Frank |
| 2 | Eric |
| 3 | Charlie |
+------+--------+
3 rows in set (0.00 sec)
第四段:undo日志文件的管理
默认情况下,undo日志在InnoDB存储引擎的数据目录下的ibdata文件中保存。但是,您可以使用单独的undo日志文件来代替它。进程的undo日志条目不是要求之间的同步,因此可以设置多个存储设备进行并发操作。
mysql> show variables like '%undo%';
+--------------------------+--------+
| Variable_name | Value |
+--------------------------+--------+
| innodb_undo_directory | ./ |
| innodb_undo_log_encrypt | OFF |
| innodb_undo_log_truncate | OFF |
| innodb_undo_tablespaces | 0 |
+--------------------------+--------+
4 rows in set (0.00 sec)