Mysql-事务

事务:是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合

事务的特性(ACID)

1 、原子性 Atomicity
事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做 ,实现事务的原子性,是基于日志的Redo/Undo机制
2 、一致性Consistent
一致性是指执行事务前后的状态要一致,可以理解为数据一致性。
3 、隔离性Isalotion
一个事务的执行不能其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。隔离性侧重指事务之间相互隔离,不受影响,这个与事务设置的隔离级别有密切的关系。
--两个事务同时操作同一数据时,先执行的事务会锁住数据,待数据释放时候才会执行下一个事务。
4 、持续性 Durable
也称永久性,指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响。

Redo/Undo:

将所有对数据的更新操作都写到日志中。
Redo log用来记录某数据块被修改后的值,可以用来恢复未写入 data file 的已成功事务更新的数据;
Undo log是用来记录数据更新前的值,保证数据更新失败能够回滚。
例子:假如某个时刻数据库崩溃,在崩溃之前有事务A和事务B在执行,事务A已经提交,而事务B还未提交。当数据库重启进行 crash-recovery 时,就会通过Redo log将已经提交事务的更改写到数据文件,而还没有提交的就通过Undo log进行roll back。

事务的隔离级别

读未提交(READ UNCOMMITTED)
读提交 (READ COMMITTED)Oracle, SQL Server的默认隔离级别
可重复读 (REPEATABLE READ)MySQL的默认隔离级别
串行化 (SERIALIZABLE)
读未提交: 读未提交会读到另一个事务的未提交的数据,产生脏读问题
读提交: 读提交则解决了脏读的,出现了不可重复读,即在一个事务任意时刻读到的数据可能不一样,可能会受到其它事务对数据修改提交后的影响,一般是对于update的操作。(例如, A、B两个事务,A事务先读取了数据, B事务更新了数据,A再次读取时数据与原先不一致,即为读脏数据)
重复读:一个事务开始时其余事务不能对数据进行修改。避免了不可重复读,但还有可能出现幻读。 (幻读: 对数据库执行操作前读取的数据和操作时的数据不一致)
串行化:各个事务依次执行

事务的底层实现

读提交和可重复读都是使用MVVC(多版本并发控制)方式进行实现。
实现原理:一致性视图(快照)
在实现可重复读的隔离级别,只需要在事务开始的时候创建一致性视图,也叫做快照,之后的查询里都共用这个一致性视图,后续的事务对数据的更改是对当前事务是不可见的,这样就实现了可重复读
读提交每一个语句执行前都会重新计算出一个新的视图,这个也是可重复读和读提交在MVCC实现层面上的区别。
》快照(视图)在MVCC底层是怎么工作的
在InnoDB 中每一个事务都有一个自己的事务id,并且是唯一的,递增的, 对于Mysql中的每一个数据行都有可能存在多个版本,在每次事务更新数据的时候,都会生成一个新的数据版本,并且把自己的数据id赋值给当前版本的row trx_id
》对于一个快照来说,你知道它要遵循什么规则
对于一个事务视图来说除了对自己更新的总是可见,另外还有三种情况:
1.版本未提交的,都是不可见的;
2.版本已经提交,但是是在创建视图之后提交的也是不可见的;
3.版本已经提交,若是在创建视图之前提交的是可见的
》两个事务执行写操作,又怎么保证并发
假如事务1和事务2都要执行update操作,如果查询条件使用过了索引,可以快速获取数据行事务1先update数据行的时候,先会获取行锁,锁定数据,当事务2要进行update操作的时候,也会取获取该数据行的行锁,但是已经被事务1占有,事务2只能wait,若是事务1长时间没有释放锁,事务2就会出现超时异常 。如果没有使用索引,没有办法快速定位到数据行就获取所有行,都加上行锁,然后Mysql会再次过滤符合条件的的行并释放锁,只有符合条件的行才会继续持有锁,消耗也会比较大。
https://zhuanlan.zhihu.com/p/148035779

你可能感兴趣的:(Mysql-事务)