# distribute-transaction **Repository Path**: kepler_wang/distribute-transaction ## Basic Information - **Project Name**: distribute-transaction - **Description**: No description available - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 69 - **Created**: 2022-07-22 - **Last Updated**: 2022-07-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 事务 事务测试 https://gitee.com/dromara/distribute-transaction ## 1. mysql数据不一致问题 mysql 事务并发时,数据不一致问题 1. 更新丢失(脏写): 写操作冲突,后提交的事务,覆盖了先提交的事务的更新结果 2. 脏读: 一个事务A读到了另一个事务B未提交的数据,如事务B回滚则A读到了脏数据 3. 不可重复读: 一个事务读取了某些数据,在一段时间后,这个事务再次读取之前读过的数据,此时发现读取的数据发生了变化, 或者其中的某些记录已经被删除 4. 幻读: 一个事务按照相同的查询条件重新读取之前读过的数据,发现其他事务插入了满足当前查询条件的新数据 一个事务两次读取一个范围的数据记录,两次读取到的结果不同 ## 2. mysql事务 InnoDB提供事务隔离级别:读未提交(Read Uncommitted), 读已提交(ReadCommitted), 可重复读(Repeatable Read), 串行化(Serializable) (1)--transaction-isolution命令 set {SESSION | GLOBAL} TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE} 1. 不带SESSION和GLOBAL关键字设置事务隔离级别,指的是为下一个(还未开始的)事务设置隔离级别 2. GLOBAL指对全局设置事务隔离级别,对所有新产生的连接生效;SESSION是对当前的数据库连接设置事务隔离级别,只对当前连接的后续事务生效 3. 查询事务隔离级别:SELECT @@global.tx_isolation; SELECT @@session.tx_isolation; SELECT @@tx_isolation (2)修正my.cnf my.ini文件内配置 transaction-isolution = {READ-UNCOMMITTED | READ_COMMITTED | REPEATABLE-READ | SERIALIZABLE} ## 3. mysql事务隔离级别 区别 1.读未提交 脏读:可能 不可重复读:可能 幻读:可能 2.读已提交 脏读:不可能 不可重复读:可能 幻读:可能 3.可重复读 脏读:不可能 不可重复读:不可能 幻读:可能 4.串行化 脏读:不可能 不可重复读:不可能 幻读:不可能 Oracle默认的事务隔离级别:读已提交 Mysql InnoDB默认的事务隔离级别:可重复读 可重复读使用MVCC机制,对数据进行版本管理,select属于快照读,不会更新数据版本; 操作数据(insert,update,delete)会更新版本号,是当前读 解决幻读:串行化事务隔离级别,或者间隙锁和临键锁 ## 4. mysql事务原理 ### 1. Redo Log 事务原子性和持久性是由Redo Log保证;确保mysql事务提交后,事务所涉及的所有操作要么全部执行成功,要么全部失败 InnoDB 所产生的日志,物理日志,是对磁盘上的数据进行修改操作, Redo Log用来恢复提交后的物理数据页 包含两部分:1.内存中的日志缓冲, Redo Log Buffer,掉电后丢失; 2.存放在磁盘上的重做日志文件,称作Redo Log File ![images](images/redoLog.png) Redo Log刷盘规则 ![images](images/redoLog1.png) 1. 开启事务,发出提交事务指令后是否刷新日志由变量 innodb_flush_log_at_trx_commit决定 innodb_flush_log_at_trx_commit取值 0, 1, 2,默认1 0 代表每次提交事务时,不会将Log Buffer中的日志写入OS Buffer,而是通过一个单独线程,每秒写入OS Buffer,并通过fsync()函数写入Redo Log 文件 非实时,效率较高,但是系统崩溃时可能丢失1s的数据 1 每次提交事务,都会将Log Buffer中的日志写入OS Buffer, 同时通过fsync()写入Redo Log文件 实时,系统崩溃不会丢失数据,性能较差 2 每次提交事务,只写入OS Buffer 并fsync()写入Redo Log 2. 每秒刷新一次,刷新日志的频率由变量innodb_flush_log_at_timeout的值决定,默认是1s; 频率与是否执行commit无关 3. 当Log Buffer中已经使用的内存超过一半时,也会触发刷盘操作