常州网站建设czyzj,五星级酒店网站建设,微网站做下载链接,一人可做的加盟店事务特性
数据库事务具有以下四个基本特性#xff0c;通常被称为 ACID 特性#xff1a; 原子性#xff08;Atomicity#xff09;#xff1a;事务被视为不可分割的最小工作单元#xff0c;要么全部执行成功#xff0c;要么全部失败回滚。这意味着如果事务执行过程中发生…事务特性
数据库事务具有以下四个基本特性通常被称为 ACID 特性 原子性Atomicity事务被视为不可分割的最小工作单元要么全部执行成功要么全部失败回滚。这意味着如果事务执行过程中发生了错误所有的修改都将被回滚数据库状态将回到事务执行前的状态。 一致性Consistency事务执行前后数据库从一个一致性状态转换到另一个一致性状态。事务的执行不会破坏数据库的完整性约束例如主键、外键约束等。数据库会保持数据的完整性和一致性。 隔离性Isolation每个事务的操作都相互隔离一个事务的中间结果对其他事务是不可见的。这意味着一个事务的修改在提交之前对其他事务是不可见的防止了并发事务之间的相互影响保证了数据的正确性。 持久性Durability一旦事务提交成功对数据库的修改就会永久保存即使系统故障或崩溃也不会丢失。数据库会将事务的结果持久化到非易失性存储器中以保证即使系统发生故障数据也不会丢失。
这些特性确保了数据库事务的可靠性和稳定性。它们是数据库管理系统中设计用于支持可靠性和并发控制的重要概念。通过保证事务具有这些特性数据库可以提供稳定、可靠、高效的数据管理和处理能力。
事务的隔离级别
事务的隔离性
事务完全的串行会严重的降低系统的吞吐量和资源利用率仔细发现引发事务一致性问题的根本原因在于多个事务访问了相同的数据更合理的做法是在某个事务访问某个数据时对其他想要访问该数据的事务进行限制当该事务提交后其他事务才能继续访问这个数据
事务并发执行引发的一致性问题
脏读
一个事务读取了另一个未提交事务修改过的数据意味着发生了脏读脏读引发的事务一致性问题。T1事务读取了T2事务未提交的数据。 幻读和不可重复读是并发事务中可能出现的两种问题它们在数据库事务隔离级别较低的情况下会更容易发生。它们之间的区别在于以下几点
幻读Phantom Read
幻读指的是在同一个事务内多次执行同样的查询但在查询中返回了不同的数据行的现象。这种情况通常发生在一个事务中插入数据后另一个并发事务再执行相同的查询发现结果集中出现了之前不存在的行。
不可重复读Non-repeatable Read
不可重复读指的是在同一个事务内多次执行同样的查询但在查询中返回了不同的数据行的现象。与幻读不同的是不可重复读是由于其他并发事务对数据进行了修改导致的。
总的来说**幻读侧重于事务在查询中发现了之前不存在的数据行而不可重复读侧重于事务在多次读取相同数据时发现数据被其他事务修改。**两者的根本区别在于幻读关注的是新增或者删除的数据行而不可重复读关注的是已经存在的数据行发生了改变。
SQL标准中的四种隔离级别
设置隔离级别的目的是舍弃一部分隔离性换取一部分性能SQL标准中的4个隔离级别
隔离级别脏读不可重复读幻读READ UNCOMMITTED允许允许允许READ COMMITTED不允许允许允许REPEATABLE READ不允许不允许允许SERIALIZABLE不允许不允许不允许
MySQL中支持的4中隔离级别
MySQL中的默认隔离级别是REPEATABLE READ MySQL8查询事务隔离级别
SELECT GLOBAL.transaction_isolation;修改隔离级别语句
set [global | session] transaction isolation level 隔离级别;各种隔离级别适用的场景 READ UNCOMMITTED (读未提交): 这个隔离级别适用于某些特定的报表查询场景对数据的实时性要求非常高而对数据一致性要求较低。例如在某些实时监控系统中可以使用读未提交隔离级别来获取最新的数据即使数据可能尚未被完全提交。 READ COMMITTED (读已提交): 这个隔离级别适用于大多数在线交易处理系统OLTP如电子商务网站。在这种场景下用户只需要读取已经提交的数据以避免看到其他事务未提交的数据。一个典型的例子是在线购物系统中的库存管理确保每个用户看到的库存数据是准确的。 REPEATABLE READ (可重复读): 这个隔离级别适用于某些需要对数据进行长时间读取或计算的场景比如报表生成或复杂的分析。在这些情况下确保事务在执行期间不受其他事务的影响是非常重要的以避免数据不一致性。例如某些财务报表的生成过程中需要保证数据的完整性和一致性。 SERIALIZABLE (可串行化): 这个隔离级别适用于某些极端要求数据完全一致性的场景如金融交易系统。在这种系统中任何数据的不一致性都可能导致严重的后果。因此确保所有事务按顺序逐个执行是至关重要的即使在高并发情况下也要保证数据的完整性。
MVCC原理多版本并发控制
版本链
在InnoDB存储引擎中的表聚簇索引中的记录都包含两个隐藏列 trx_id 一个事务都某条聚簇索引记录进行修改时都会把该事务的事务id赋值给trx_id roll_pointer 每次对聚簇索引记录进行改动时都会把旧的版本写入到undo日志中相当于一个指针通过它可以找到该记录修改前的信息
ReadView读视图
用READ UNCOMMITTED 隔离级别的事务来说可以读取未提交事务修改的记录因此直接读取版本链中的最新版本就可以了对于SERIALIZABLE隔离级别的事务来说InnoDB中使用加锁的方式访问记录对于READ COMMITED和REPEATABLE READ隔离级别的事务来说都必须保证读到的记录是已经提交的事务修改过的记录因此核心问题就是需要判断版本链中的哪个版本对于当前事务是可见的InnoDB给出的解决方案是生成ReadViewReadView包含下列四个重要内容 m_ids:生成ReadView时当前系统中活跃的事务id列表 min_trx_idm_ids中的最小事务id max_trx_id在生成ReadView时系统分配个下一个事务的事务id(max_trx_id1) creator_trx_id生成该ReadView的事务的事务id 生成了ReadView之后我们就可以借助它来判断当前版本的记录对当前事务是否可见
如果当前记录的trx_id与creator_trx_id相同意味着当前事务在访问自己修改过的记录可以访问如果当前记录的trx_id小于min_trx_id说明生成该版本记录的事务已经提交了可以访问如果当前记录的trx_id 大于max_trx_id说明生成该版本的事务在当前事务生成ReadView之后才开启所以该版本不可以被当前事务访问如果被访问版本的trx_id 在 min_trx_id 和 max_trx_id之间则需进一步判断trx_id是否在m_ids列表中如果在说明事务为提交该版本不可见如果不在说明可见
在MySQL中READ COMMITED和REPEATABLE READ 隔离级别之间一个非常答的区别就是他们生成ReadView的时机不同
READ COMMITED 每次读取数据前都生成一个ReadView
例如现在系统中有两个事务id为T100T200的事务正在执行T80是已经提交的事务。100的事务修改a1,200的事务修改a2,下面是表信息其中第一行索引中的记录。
idatrx_idroll_point1110010011100801080
假设现在有一个使用READ COMMITED隔离级别的新事物开始执行 执行语句为
select a from t where id1;select语句执行过程如下
执行select语句时生成一个ReadViewm_ids列表为[100,200]min_trx_id为100max_trx_id为201creator_trx_id为0 因为这个新开启的事务只进行了select操作并没有对记录进行修改所以系统没有为其分配事务id默认为0 顺序版本链寻找符合要求的版本返回的是a为0的版本
之后将事务id为100的事务提交事务 200 事务中更新表 hero number 的记录
update t set a 2 where id1然后再到刚才使用 READ COMMITTED隔离级别的事务执行select语句继续查找number为1 的记录执行步骤如下
生成ReadViewm_ids列表[200]min_trx_id为200max_trx_id为200creator_trx_id为0顺序版本链查找符合要求的版本最终返回的是1
REPEATABLE 在第一次读取数据时生成一个ReadView
假设现在有一个使用 REPEATABLE READ 隔离级别的新事务开始执行 第一次select操作时
生成ReadView执行select语句时生成一个ReadViewm_ids列表为[100,200]min_trx_id为100max_trx_id为201creator_trx_id为0找到符合条件的版本0
之后将事务id为100的事务提交后再到事务id为200的事务中更新表中id为1的记录 然后再次执行select
沿用或者说复制第一次select时生成的ReadView最终的返回版本还是0
总结在REPEATABLE READ隔离级别下事务的两次查询结果是一样的因此可以说在REPEATABLE READ级别下避免了不可重复读的发生同时也很大程度上避免了幻读的发生
MVCC小结
所谓的MVCC指的就是在使用READ COMMITED 和 REPEATABLE READ这两种隔离级别的事务在执行select操作时访问记录版本链的过程这样可以使不同事务的读-写操作并发执行从而提升系统性能。READ COMMITED 和 REPEATABLE READ的最大区别在于生成Read View的时机不同READ COMMITED 每次执行select前都会生成一个新的ReadView而REPEATABLE READ只在第一次执行select前生成一个ReadView