1.数据库事务的四大特性以及事务的隔离级别
  • 原子性:要么全部成功,要么全部失败回滚
  • 一致性:比如两个用户转钱,无论怎么转,最后总额肯定一样。
  • 隔离性:多个线程操作后台会隔离
  • 持久性:事务完毕后哪怕数据库宕机重启后还是一样。
2.事务的隔离级别
  • 脏读:一个事务读取另一个事务未提交的数据。
  • 不可重复读:不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。
  • 幻读:幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数,主要针对新增的数据)。
  • 序列化:这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
3.MySQL数据库为我们提供的四种隔离级别
  • ① Serializable (串行化):可避免脏读、不可重复读、幻读的发生。性能不好!

  • ② Repeatable read (可重复读):可避免脏读、不可重复读的发生。保证一个事务不能读取另一个事务未提交的数据。(Mysql默认),还会有幻读

  • ③ Read committed (读已提交):可避免脏读的发生。(还会有幻读,可充复读)

  • ④ Read uncommitted (读未提交):最低级别,任何情况都无法保证。

查看 Mysql 数据库事务隔离级别

1.查看当前会话隔离级别
select @@tx_isolation;
2.查看系统当前隔离级别
select @@global.tx_isolation;
3.设置当前会话隔离级别
set session transaction isolatin level repeatable read;
4.设置系统当前隔离级别
set global transaction isolation level repeatable read;
4.事务的传播级别
  • 大概就是在一个事务内,对子方法的事务级别进行控制,如创建一个新的事务。

    注意的是:动态代理给spring留下的坑!spring中使用都是无效的,需要创建上下文对象application执行子方法,或者使用aopContext代理,也或者是spring注入对象调用才生效。

性能上分类: 悲观锁、乐观锁

操作类型上:读锁、写锁

数据粒度上:表锁、行锁、页面锁 行锁加在索引上,并且索引不能失效,不然有可能变表锁。for update 排他锁,lock in share mode 共享锁。

更细粒度:间隙锁、临键锁

间隙锁:针对两个值的范围之间进行加锁,如 ID 范围在(1,15] 之间,MVCC和行锁+间隙锁解决幻读。

临键锁:行锁和间隙锁的组合

redo log

保证事务的原子性和持久性,避免内存中的脏数据写入数据表 IBD 文件,针对的是内存中数据页的修改操作。

执行sql,写入数据到内存中的 redo log buffer,根据一定规则写入磁盘 redo log,数据库故障时通过 redo log 进行恢复到 idb 文件。

Redo Log buffer 写入到日志 redo log 示意图

刷盘规则

用户空间的 redo log buffer 写入磁盘 redo log 需要进过系统内核 os buffer,刷盘可以根据下面规则。

  • 事务 commit 就刷盘
  • 每秒都刷盘
  • log buffer 占用内存就刷盘
  • 事务中存在检查点时。

redo log写入规则

把 redo buffer 的写入redo log 中,redo log 中存在两个东西,一个是 wirte pos 记录着数据表记录的位置,另一个是 check point 检查点负责擦除。存在间隔代表还可以继续记录新的操作。

LSN

表示日志的逻辑序列号。

undo log

用于回滚事务和多版本控制MVCC,记录逻辑日志,每次执行 sql 增加一条回滚 SQL 语句。比如新增语句 insert 时记录一条 delete 语句,执行 update 语句时记录一条反向的 update 语句。如果数据库崩溃,先恢复 redo log 再恢复 undo log。

MVCC(Multi-Version Concurrent Control)

MVCC叫做多版本并发控制,实际上就是保存了数据在某个时间节点的快照readView

我们每⾏数实际上隐藏了两列,创建时间版本号,过期(删除)时间版本号,每开始⼀个新的事务,版本号 都会⾃动递增。查询 select 不会更新版本号,但是插入 insert,更新 update, 删除 delete 会更新版本号。

binlog

mysql 自身的二进制日志,主要用于主从复制和数据恢复。一个事务的 binlog 是完整的不会插入其他事务的 binlog。

拥有3个记录模式:

  • row 模式 每一行操作都记录,日志会很庞大
  • statement 模式 不记录细节,只记录结果,有些 sql 如 now(), last_insert_id() 等会不一致。
  • 混合模式 上面两种结合

binlog 和 redo log 的区别

redolog binlog
innodb特有 mysql本身就有
记录内存中的数据页修改 记录所有操作
先写缓存区,写入完成提交事务 每个sql写入内存缓存或者一个事务提交一次性写入内存缓存
循环写日志,通过记录检查点和write pos 一直追加写入
用于数据库崩溃自动恢复 用于主从和数据恢复
上次更新时间: 2024/5/7 05:59:02