数据库事务和隔离级别

数据库事务的定义:一个或多个数据库操作

事务的四大特性

A atom 原子性 事务执行是原子,一个事务中所有操作,要么全部完成,要么全部不完成,不会结束在中间的环节。

C Consistency 一致性 在事务开始和事务开始后,数据库的完整性约束没被破坏完整性约束:主键的约束没有变,数据库中不能输入不符合约束的值。

I isolation 隔离性 多个并发事务相互独立互不影响,多个用户的并发事务访问同一个数据库,一个用户的事务应该被隔离起来不被干扰。

D durability 持久性 事务处理后对数据的修改是永久的

Mysql 事务是如何实现的

原子性:通过undo log实现的。每条数据变更都伴随一条undo log日志的生成,当系统发生错误或执行回滚根据undo log做逆向操作。
持久性:通过redo log实现的。redo log记录了数据的修改日志。数据持久化到磁盘,先是储存到缓冲池里,然后缓冲池中的数据定期同步到磁盘中,如果系统宕机,可能会丢失数据,系统重启后会读取redo log恢复数据。
隔离性:mysql数据库通过MVCC + next-key机制实现了隔离性
一致性:以上3大特性,保障了事务的一致性

mysql四种隔离级别

1、读未提交

如果一个事物已经开始写数据,则另外一个事物则不允许同时进行写操作,但是允许读数据,会出现脏读。

2、读已提交

未提交的写事务禁止其他事物访问,可避免脏读

3、可重复读(数据库默认隔离级别)

sql第一次读取到数据后,就将这些数据加锁(悲观锁),其它事务无法修改这些数据,就可以实现可重复读了。

​ 可避免脏读,不可重复读

4、串行化

​ 可避免脏读、不可重复读和幻读

隔离界别 脏读 不可重复读 幻读
READ UNCOMMITTED:读未提交 可能发生 可能发生 可能发生
READ COMMITTED:读已提交 解决 可能发生 可能发生
REPEATABLE READ:可重复读 解决 解决 可能发生
SERIALIZABLE:可串行化 解决 解决 解决

不考虑隔离级别会发生的事情

1、脏读

一个事务在处理数据时读到别的未提交事务的数据,然后这个数据回滚了

2、不可重复读

数据库中的某个数据,在一次事务中多次查询得到的数据不一致,因为另一个事务修改并且提交了

3、幻读

在一次事务里面,多次查询之后,查询的结果集的个数不一致的情况叫做幻读。而多出来或者少的哪一行被叫做 幻行但是不可重复读是一个数据,幻读是一批数据整体,解决不可重复读的办法是行锁,解决幻读的办法是锁表

数据库三大范式

  • 第一范式

    一列不能有多个值

  • 第二范式,属性完全依赖于主键 [ 消除部分子函数依赖 ]

    非主属性完全依赖于主关键字

    (学号, 课程名称) → (姓名, 年龄, 成绩, 学分)

    这个数据库表不满足第二范式,因为存在如下决定关系:

    (课程名称) → (学分)

    (学号) → (姓名, 年龄)

    即存在组合关键字中的字段决定非关键字的情况。

  • 第三范式 属性不依赖于其它非主属性 [ 消除传递依赖 ]

​ (学号) → (所在学院) → (学院地点, 学院电话) 这样是不符合的,得分成两个表

学生:(学号, 姓名, 年龄, 所在学院);

学院:(学院, 地点, 电话);

Mysql的事务该怎么手写

begin;
xxxx
commit;

or

begin;
rollback;

两阶段提交

两阶段提交的第一阶段 (prepare阶段):写rodo-log 并将其标记为prepare状态。

紧接着写binlog

两阶段提交的第二阶段(commit阶段):写bin-log 并将其标记为commit状态。

两阶段写日志用意

​ 两阶段提交的主要用意是:为了保证redolog和binlog数据的安全一致性。只有在这两个日志文件逻辑上高度一致了。你才能放心地使用redolog帮你将数据库中的状态恢复成crash之前的状态,使用binlog实现数据备份、恢复、以及主从复制。而两阶段提交的机制可以保证这两个日志文件的逻辑是高度一致的。没有错误、没有冲突。

如何判断binlog和redolog是否达成了一致

当MySQL写完redolog并将它标记为prepare状态时,并且会在redolog中记录一个XID,它全局唯一的标识着这个事务。而当你设置sync_binlog=1时,做完了上面第一阶段写redolog后,mysql就会对应binlog并且会直接将其刷新到磁盘中。

下图就是磁盘上的row格式的binlog记录。binlog结束的位置上也有一个XID。

只要这个XID和redolog中记录的XID是一致的,MySQL就会认为binlog和redolog逻辑上一致。就上面的场景来说就会commit,而如果仅仅是rodolog中记录了XID,binlog中没有,MySQL就会RollBack


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!