数据库事务和隔离级别
数据库事务的定义:一个或多个数据库操作
事务的四大特性
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 协议 ,转载请注明出处!