首页 > 数据库 >mysql 事务与隔离级别

mysql 事务与隔离级别

时间:2023-05-17 15:50:51浏览次数:36  
标签:事务 log no buffer 级别 name mysql redo 隔离

ACID

  • Atomicity:原子性(UNDO LOG实现),一组操作要么都成功,要么都失败
  • Consistency:一致性(UNDO LOG实现),从一个合法状态变为另一个合法状态(语义上不是语法上)。比如转账之后余额为负数,虽然也能守恒,但是明显不合法。或者转账时A账户钱少了,B账户钱没多,也是不合法的
  • Isolation:隔离性(锁机制实现),一个事务执行不受其他事务干扰(并发时事务是隔离的,互不干扰)
  • Durability:持久性(REDO LOG实现),事务一旦提交不能再回滚

数据并发问题

  • 脏写(Dirty Write),也叫修改丢失
    • 事务A修改了事务B回滚的数据
    • A 把 name 改成 张三,B把 name 改成李四,A 先提交,这时 name 就是张三,然后B回滚,name又改成最初的值了
  • 脏读(Dirty Read)
    • 事务A读取了事务B回滚的数据
    • B 修改 name 为李四还没提交,此时A去读就会得到 name 是李四,等A读完,B回滚
  • 不可重复读(Non-repeatable Read)
    • 事务A读取了 name,事务B修改了 name(提交了),事务A再次读发现 name 不一样了。每次读取值都会不一样
    • 这个讲道理是合法的,因为修改了值所以别人读到的值就不一样。但是这也确实是一个问题:每次读都不一样
  • 幻读(Phantom)
    • 事务A第一次读有1行数据,事务B插入了几行,事务A再次读,发现行数变多了
    • 和不可重复度类似,讲道理是合法的,区别是一个是更新一个是插入导致

事务隔离级别

用来解决数据并发产生的问题,如果都要解决性能会受影响,所以需要平衡数据准确性和并发能力选择合适的级别
数据问题严重排序:脏写 > 脏读 > 不可重复读 > 幻读

隔离级别 脏读可能性 不可重复读可能性 幻读 加锁读
READ UNCOMMITED(读未提交) yes yes yes no
READ COMMITED(读已提交 oracle 默认) no yes yes no
REPEATABLE READ(可重复读 mysql 默认) no no yes no
SERIALIZABLE(串行化) no no no yes
  • 四种级别都能解决脏写
  • SERIALIZABLE 串行化就把并行变成了串行所以能解决所有问题,并发能力最低
  • 查看隔离级别
    • 5.7.20 (包括)之前 : SHOW VARIABLES LIKE 'tx_isolation'
    • 5.7.20之后: SHOW VARIABLES LIKE 'transaction_isolation'
    • 所有版本都适用: SELECT @@transaction_isolation;
  • 设置隔离级别
    • set global transaction isolation level repeatable read;
    • GLOBAL 和 SESSION 区别:GLOBAL 对新的连接生效,当前是无效的

事务日志

分为 redo 和 undo 日志,分别保证【持久性】和【原子性、一致性】
每次服务启动都会申请一片连续的内存空间作为 redo buffer,redo buffer 会刷到 redo log 中

redo

  • 为什么需要 redo log?
    • 保证数据的持久性
    • 数据库和磁盘是以页为交互基本单位,哪怕该一个字段,也要读取一个完整的数据页,然后再刷盘,刷盘成本是很大的
    • 可以不每次事务提交都刷盘,让保存在一个 redo log 中,后面再同步 redo log 和 磁盘(不需要每次dml都更新磁盘)
  • redo log 数据来自于哪?
    • 来自于 redo buffer
  • redo buffer?
    • 每次服务启动都会申请一片连续的内存空间作为 redo buffer
    • show variables like '%innodb_log_buffer_size%' 查看当前 redo buffer 大小,默认16m
  • redo log 特点
    • 是顺序写入的
    • 事务执行过程中 redo log 不断记录(事务中有几条 dml 就记录多少次,bin log 是遇到 commit 记录所有的 dml,只记录一次)
  • redo log 物理文件
    • ib_logfile0 和 ib_logfile1
    • 在 mysql 数据目录下
  • redo log 流程
    • 事务开始
    • 读取数据到内存(将要修改的数据)
    • 更新内存的数据保存在 redo buffer 中(修改后的数据)
    • redo buffer 中的数据刷到 redo log 中(物理文件)
    • 刷盘(有3中策略,通过 innodb_flush_log_at_trx_commit 参数确定,默认是 1 )

undo

  • 为什么需要 undo log?
    • 保证数据的原子性和一致性,回滚数据
  • undo log 数据来自于哪?
    • 来自于原来的数据
    • 当需要删除时,会把删除前的数据写入 undo log;当需要更新时,把更新前的数据写入 undo log

标签:事务,log,no,buffer,级别,name,mysql,redo,隔离
From: https://www.cnblogs.com/hangychn/p/17408925.html

相关文章

  • mysql 锁机制
    表锁:InnoDB支持行锁,不代表着就不支持表锁表锁的S和X锁,MyISAM的锁(不建议在InnoDB中使用)--查看当前有表锁的表showopentableswherein_use>0;--给表加S锁(所有事务都能读,所有事务都不能写)locktablestable_nameread;--给表加X锁(拿到锁的事务可写可读......
  • mysql 底层数据存储结构
    内存和磁盘每次交互都是完整的页,数据页里面存放的是行(不仅仅是数据库的数据行,还有行格式等)页(16k,计算机与内存的最小单位)的上层单位还有区(一个区存放64个页,64*16k=1024k,刚好1M),区上面是段(一个或多个区组成),段上面是表空间(一个或多个段组成)行格式showtablestatuslike't_u......
  • docker 部署nacos单机版并配置mysql支持
    1.配置mysql数据库选用mysql5.7表名为nacos_config,附上建表SQLSETNAMESutf8mb4;SETFOREIGN_KEY_CHECKS=0;--------------------------------Tablestructureforconfig_info------------------------------DROPTABLEIFEXISTS`config_info`;CREATETABLE......
  • springboot中使用application.properties配置mysql和sqlserver
    1.使用依赖*mysql:<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency>*sqlserver:<dependency><groupId>com.microsoft.sqlserver</groupId><art......
  • mysql 存储引擎和索引
    存储引擎引擎特性文件InnoDB默认,支持事务,支持外键,支持行锁和表锁.frm文件存储表结构.ibd文件存储数据和索引MyISAM不支持事务,不支持外键,只支持表锁不支持行锁专门维护了一个常量保存每个表的总记录数(count很快)MyISAM强调的是性能,所以性能上优于InnoDB,但安全......
  • 玩转MYSQL数据库之--视图详解
    前言从今天开始本系列文章就带各位小伙伴学习数据库技术。数据库技术是Java开发中必不可少的一部分知识内容。也是非常重要的技术。本系列教程由浅入深, 全面讲解数据库体系。 非常适合零基础的小伙伴来学习。全文大约【1297】字,不说废话,只讲可以让你学到技术、明白原理的纯......
  • 关于使用Serilog配置MySql数据库和appsettings的问题
    1、项目使用dtonet6WebApi。2、Nuget包:用来访问mysql数据库Pomelo.EntityFrameworkCore.MySqlSerilog日志Serilog配合dotnetSerilog.AspNetCore读取环境变量配置Serilog.Settings.ConfigurationSerilog读取MySqlSerilog.Sinks.MySQL输出到控制台中Serilog.Sinks.Co......
  • 面试官:MySQL 日期时间类型怎么选?
    构建数据库写程序避免不了使用日期和时间,对于数据库来说,有多种日期时间字段可供选择,如timestamp和datetime以及使用int来存储unixtimestamp。不仅新手,包括一些有经验的程序员还是比较迷茫,究竟我该用哪种类型来存储日期时间呢?那我们就一步一步来分析他们的特点,这样我们根据......
  • mysql 基础知识
    --_在mysql中是表示任一字符,下面查的是名字等于*Aaaa的SELECT*FROMUSERWHERENAME='_Aaaa';--如果就要查名字是_Aaaa的人需要使用转移字符,把_当成普通字符SELECT*FROMUSERWHERENAME='\_Aaaa';--或者自定义字符SELECT*FROMUSERWHERENAME='$_Aaaa'......
  • 一个好用的命令行mysql客户端 mycli
    官网:https://www.mycli.net/支持自动补全,高亮提示,非常好用;查看表结构\dtsys_menu;有点遗憾的是没有展示注释信息,不可也可以用其它语句查看:showfullcolumnsfromsys_menu;showcreatetablesys_menu;查询结果导出\Tcsv;\o~/export.csv;SELECT*FROMt_t......