写点什么

Mysql 的事务操作问题

作者:黎燃
  • 2022 年 5 月 07 日
  • 本文字数:1409 字

    阅读完需:约 5 分钟

Mysql的事务操作问题

什么是数据库事务?

一组 sql 语句组成的数据库逻辑处理单元,在这组的 sql 操作中,要么全部执行成功,要么全部执行失败。


事务支持是在引擎层实现的。MySQL 原生的 MyISAM 引擎不支持事务,这也是 MyISAM 被 InnoDB 取代的重要原因之一。

你能说一说 Redo/Undo 机制吗?

Redo/Undo 机制比较简单,它们将所有对数据的更新操作都写到日志中。


Redo log 用来记录某数据块被修改后的值,可以用来恢复未写入 data file 的已成功事务更新的数据;Undo log 是用来记录数据更新前的值,保证数据更新失败能够回滚。


假如数据库在执行的过程中,不小心崩了,可以通过该日志的方式,回滚之前已经执行成功的操作,实现事务的一致性。


例子:假如某个时刻数据库崩溃,在崩溃之前有事务 A 和事务 B 在执行,事务 A 已经提交,而事务 B 还未提交。当数据库重启进行 crash-recovery 时,就会通过 Redo log 将已经提交事务的更改写到数据文件,而还没有提交的就通过 Undo log 进行 roll back。

那回滚日志什么时候删?

当系统里没有比这个回滚日志更早的 read-view 的时候。


InnoDB 的 MVCC 实现机制 MVCC 可以认为是行级锁的一个变种,它可以在很多情况下避免加锁操作,因此开销更低。MVCC 的实现大都都实现了非阻塞的读操作,写操作也只锁定必要的行。InnoDB 的 MVCC 实现,是通过保存数据在某个时间点的快照来实现的。一个事务,不管其执行多长时间,其内部看到的数据是一致的,也就是事务在执行的过程中不会相互影响。

简述一下 MVCC 在 InnoDB 中的实现:

InnoDB 的 MVCC,通过在每行记录后面保存两个隐藏的列来实现:一个保存了行的创建时间,一个保存行的过期时间(删除时间),当然,这里的时间并不是时间戳,而是系统版本号,每开始一个新的事务,系统版本号就会递增。在 RR 隔离级别下,MVCC 的操作如下:


select 操作:InnoDB 只查找版本早于(包含等于)当前事务版本的数据行。可以确保事务读取的行,要么是事务开始前就已存在,或者事务自身插入或修改的记录。行的删除版本要么未定义,要么大于当前事务版本号。可以确保事务读取的行,在事务开始之前未删除。insert 操作:将新插入的行保存当前版本号为行版本号。delete 操作:将删除的行保存当前版本号为删除标识。update 操作:变为 insert 和 delete 操作的组合,insert 的行保存当前版本号为行版本号,delete 则保存当前版本号到原来的行作为删除标识。由于旧数据并不真正的删除,所以必须对这些数据进行清理,innodb 会开启一个后台线程执行清理工作,具体的规则是将删除版本号小于当前系统版本的行删除,这个过程叫做 purge。

例子

CREATE TABLE account (  id INT PRIMARY KEY AUTO_INCREMENT,  NAME VARCHAR(10),  balance DOUBLE);
-- 添加数据INSERT INTO account (NAME, balance) VALUES ('zhangsan', 1000), ('lisi', 1000)SELECT * FROM account;
-- 张三给李四转账 500 元 -- 0. 开启事务START TRANSACTION;
-- 1. 张三账户 -500 UPDATE account SET balance = balance - 500 WHERE NAME = 'zhangsan';
-- 2. 李四账户 +500-- 出错了...UPDATE account SET balance = balance + 500 WHERE NAME = 'lisi'; -- 发现执行没有问题,提交事务COMMIT; -- 发现出问题了,回滚事务ROLLBACK;
复制代码

事务的四大特征:

原子性:是不可分割的最小操作单位,要么同时成功,要么同时失败。持久性:当事务提交或回滚后,数据库会持久化的保存数据。隔离性:多个事务之间,相互独立。一致性:事务操作前后,数据总量不变

用户头像

黎燃

关注

前端工程师 2022.05.06 加入

专注学习分享前端知识。

评论

发布
暂无评论
Mysql的事务操作问题_MySQL_黎燃_InfoQ写作社区