需求场景:有一张银行账户表,有A用户给B用户转账,A账户先减少,B账户增加,但是A操作完之后断电了
解决方案:A减少钱,但是不要立即修改数据表,B收到钱之后,同时修改数据表
事务安全
事务:一系列要发生的连续的操作
事务安全:一种保护连续操作同时满足实现的一种机制
事务安全的意义:
保证数据操作的完整性
------创建一个账户表
Create table my_account(
Number char(16) not null unique comment “银行卡账户”,
Name varchar(20) not null,
Money decimal (10,2) default 0.0 commemt “账户余额”
)charset utf-8
--- 插入数据
Insert into my_account values(“0001”,张三,1000),(“0002”,李四,2000)
事务操作
事务操作:自动事务操作(默认,用户操作完之后立即同步到数据库,由变量autocommit控制),手动事务操作
手动事务操作:
1.开启事务,告诉系统所有操作不要直接存储到数据库,先存入到事务日志
Start transaction;或者begin;
2.进行事务操作
Update my_account set money = money -1000 where id = 1;
Update my_account set money = money + 1000 where id = 2;
关闭事务:选择性的将日志文件中的结果保存到数据库或者直接清空事务日志
- 提交事务:commit,同步数据表
- 回滚事务:rollback,直接清空日志表
可以设置回滚点 savepoint 回滚点名称,防止错误,可以回滚到回滚点的位置
例如上面的案例
可以设置回滚点:
Savepoint spl
Update my_account set money = money -1000 where id = 1;
Rollback to spl
Update my_account set money = money + 1000 where id = 2;
事务原理
事务开启之后,所有的操作都会临时保存到事务日志,事务日志只有在得到commit命令才会同步到数据表,其他清空都会清空(rollback,断电,断开连接)
事务的特点
ACID(原子性,一致性,隔离性,持久性)
原子性:众所周知,原子是不可分割的,因此原子性表示事务的一系列操作是不可分割的,一个操作步骤失败,全部重来,所有操作步骤成功才会成功。
一致性:事务的执行结果必须使数据库从一个一致性状态变换到另一个一致性状态,所谓的一致性就是指满足数据的完整性
隔离性:并发执行的事务不会相互影响
持久性:事务一旦提交,对数据库的更新是持久的
其中一致性是事务的根本追求
那么事务的特点背后实现的原理是什么呢?
原子性的实现原理:undo log(撤销日志)
Undo log是为了实现事务的原子性,在mysql数据库数据库Innodb存储引擎中,undo log来实现多版本并发控制
在操作任何一个数据之前,首先将数据备份到一个地方(undo log),然后对数据进行修改,如果一旦哪个操作失败,系统可以利用undo log备份的数据恢复到事务操作之前的状态
注意:undo log是逻辑日志,可以理解为:
Delete一条记录,undo log就会有一条insert记录
Insert一条记录,undo log就会有一条delete记录
持久性:Redo log(重做日志)
Redo log用来记录新数据的备份,在事务提交前,只要将Redo log持久化即可,不需要将数据持久化,当系统崩溃时,虽然数据没有持久化,但是redo log已经持久化,系统可以根据redo log的内容,将数据恢复到最新的状态。
隔离性:是通过读写锁+MVCC(multiple version concurrent control,多版本并发控制)
而一致性就是基于在原子性+持久性+隔离性实现的基础上实现的
隔离性级别:从低到高依次是:
读未提交(read uncommitted):指的是事务之间,即使一个事务没有commit,另外一个事务也是可以读取一个事务进行的操作
读已提交(read committed)
可重复性(repeatable read)
串行化(serializable)
隔离性如何实现,其实就是基于锁机制,在mysql中,锁分俩类:
- 共享锁:用于事务之间读取数据
- 排他锁
那么什么是锁呢?下篇文章会介绍