1. 事务
一条或多条语句的组合。
示例:有一个银行,有用户ID,用户名,余额三个字段;
1 张三 1000
2 李四 0
目标实现:
张三给李四转转账500;
具体操作:
1.要先给张三的账户-500,
2.再给李四的账户+500;
这是两条语句组成一个组合。
1.1 特性:A C I D
- 原子性:要么不做,要么就一次性完成的操作;
- 一致性:事务开始前到结束后,数据库的完整性没有被破坏,符合预设规则;
- 隔离性:保证数据库的并发操作是安全的;
- 持久性:持久化存储,防止数据的丢失。
2. 隔离性是如何实现并发操作安全的?
2.1 如果没有隔离性数据库的操作有可能出现的问题:
2.1.1 脏写:A事务做的修改被B事务的修改覆盖;
2.1.2 脏读:主要是因为读未提交而导致的;
A事务对表中数据进行修改,
在A事务还没提交之前,B事务查询到了修改的数据;
因为A事务没有完成之前,完全有可能事务回滚。
2.1.3 不可重复读:不同时间段读取的数据可能不同;
事务A对数据库中数据进行了第一次查询,得到了一个结果:100;
事务B对数据库中的数据进行了修改,并且提交了事务:200;
事务A在后面重新对数据进行查询,得到了一个与第一次不同的结果。
2.1.4 幻读:不同时间段所读取数据的条数不同;
事务A读数据库中数据进行了第一次查询salary<1w,得到了5条数据;
这时候公司新进一个员工,薪资是8k,事务B向数据库中添加了一条新的数据;
事务A再次对数据库中数据进行一次查询salary<1w,得到了6条数据。
2.2 innodb存储引擎设置了4个隔离级别用于解决不同层次的问题:
针对这三种并发操作存在的问题,
mysql数据库的innodb存储引擎设置了4个隔离级别用于解决不同层次的问题:
2.2.1 读未提交
相当于没有隔离性,会存在脏读,不可重复读,幻读的问题;
2.2.2 读提交
只能读取已经提交的事务的改变,解决了脏读的问题,但是依然存在不可重复读,幻读的问题;
2.2.3 可重复读
mysql默认的隔离级别。
当前事务中,不管其他事务对数据在做什么改变,事务有没有提交,
总是能够保证在不同时间段读取到的结果一致。
解决了不可重复读的问题,但是还依然存在幻读问题。
2.2.4 串行化
给事务强制进行排序,避免冲突,从而解决所有的并发问题。
但是因为过于极端,效率较低因此实际使用较少。
2.3 总结
3. MVCC-多版本并发控制机制
在mysql中实际上是采用了MVCC-多版本并发控制机制—解决读写并发冲突的控制;
实际上mysql相当于对数据的每个操作都做了一个版本备份起来了:undo日志;
并且数据库中的每一张表实际上都有三个隐藏字段:
事务ID,回滚指针,自增ID。
假设当前活跃的事务信息数组:2号事务活跃;
当前数据操作事务是2号事务,而2号事务是一个活跃事务,意味着这个事务还没有提交;
则这时候通过回滚指针,在undo日志中查找比自己事务ID小的,且没有在活跃事务数组中的数据。
读已提交,解决脏读问题。
4. 事务的操作
4.1 开启事务
begin & start transaction;
4.2 保存事务阶段
savepoint point_name;
4.3 回滚事务
rollback & rollback to point_name;
4.4 提交事务
commit;
一个事务一旦提交,就无法回滚了。