MYSQL事务和隔离级别,面试时如何回答
1.事务
事务是由一组SQL语句组成的逻辑处理单元。它是一组满足ACID特性的操作。您可以通过 Commit 提交事务,也可以使用 Rollback 回滚。事务具有以下 4 个属性,通常称为事务 ACID 属性:
- 原子性:事务是原子操作单元,其数据更改要么全部更改,要么无更改。执行了。例如,同一事务中的所有 SQL 语句要么成功,要么失败。可以使用日志来完成回滚。日志记录了事务执行的修改操作。这些修改操作可以在回滚时反向执行。
- 一致:当事务开始和结束时,数据必须保持一致的状态。这意味着所有相关的数据规则必须应用于交易变更以保持数据完整性;所有内部数据结构(例如 B 树索引或双向链表)在事务结束时也必须正确。以下载为例。 A向B转账,假设转账前双方的资金总额为2000。 A向B转账后,无论两个账户如何转账,用户A的钱和用户B的钱加起来都是2000,总金额仍然是2000,这就是交易的一致性。
- 隔离性:数据库系统提供了一些隔离机制,保证事务在“独立”的环境中执行,不受外部并发操作的影响。 隔离是指当多个用户同时访问数据库时,比如管理同一张表时,数据库为每个用户打开的事务不能干扰其他事务的操作,多个并发事务必须隔离彼此。也就是说,我们达到了这样的效果:对于任意两个并发事务T1和T2,从事务T1的角度来看,T2在T1开始之前结束或者在T1结束之后开始,这样每个事务对并发运行的其他事务没有任何意义。
- 永久:一笔交易一旦完成,其数据的变化就是永久的,即使系统出现故障也能被保留。 可以通过备份和恢复数据库来实现。当系统崩溃时,可以使用备份的数据库来恢复数据。
默认情况下,MySQL 接受自动发布模式。换句话说,除非您显式使用语句 BEGIN TRANSACTION
来启动事务,否则每个查询都会自动作为事务发送。
这些特性不是横向关系:
- 只有满足一致性,事务执行的结果才是正确的。
- 如果没有并发,事务是顺序执行的,必须满足隔离性。同时,只要能满足原子性,就必须满足一致性。
- 在并发的情况下,多个事务同时执行。事务不仅要满足原子性,还要满足隔离性,以实现一致性。
- 事务满足处理数据库崩溃的持久性。
2。并发一致性问题
1。丢失更新(Lost Update)
事务 T1 和 T2 都更改了一条数据。 T1 首先更改它,T2 随后更改。 T2 的变化覆盖了 T1。改变。
例如,两个程序员修改同一个java文件。每个程序员独立地修改他的副本,然后保存修改后的副本,从而覆盖原始文档。最后一个保存其更改副本的编辑者会覆盖前一个程序员所做的更改。
如果在一名程序员完成并提交事务之前另一位程序员无法访问同一文件,则可以避免此问题 。
2。脏读
一句话:事务 B 读取了事务 A 已修改但尚未提交的数据,并对该数据进行了操作。如果此时事务A回滚Rollback
,则B读取到的数据无效,不符合合规要求。
解决方案:将数据库事务隔离级别调整为READ_COMMITTED
T1修改数据,T2再读取。如果T1取消这个改变,T2读到的数据就是脏数据。
3。不可重复读取
在一个事务中多次读取相同的数据。在该事务结束之前,另一个事务访问相同的数据。然后在读取第一个事务中的数据时。第二事务的改变可能导致第一事务读取的数据不同。这样,一次事务中读取两次的数据是不同的,因此称为不可重复读,即原始读。不能重复。
使用一条语句:事务范围内两个相同的查询返回不同的数据。
同时工作。事务1在操作期间和提交后读取事务2的数据。读取记录内容不一致。 不可重复读是指在同一个事务中,两个相同的查询返回不同的结果。
解决方法:如果修改事务完全提交后才能读取数据,则可以避免此问题。将数据库事务隔离级别调整为REPEATABLE_READ
T2 读取数据,T1 修改数据。如果T2再次读取该数据,此时读取的结果与第一次读取的结果不同。
4。幻读
事务T1根据相同的查询条件重新读取之前取出的数据,却发现另一个事务T2插入了符合其查询条件的新数据。这种现象称为“幻读”。 (与可重复读类似,但事务T2的数据操作只是插入和删除,不是数据修改,并且读取的记录条数不一致)
一句话:事务A读取了事务B提交的新数据,不满足隔离要求
解决方案:如果在操作事务处理完数据之前没有其他事务可以添加新数据,则可以避免此问题。将事务数据库隔离级别调整为SERIALIZABLE_READ
。
T1读取指定范围内的数据,T2在该范围内插入新数据,T1再次读取该范围内的数据。此时读取的结果与第一次读取的结果不同。
3。事务隔离级别
“脏读”、“不可重复读”和“幻读”实际上是数据库读一致性问题, 必须通过提供某种事务隔离机制的数据库来解决。
数据库事务隔离越严,并发的副作用就越小,但付出的代价就越大,因为事务隔离实质上使事务在一定程度上“序列化”,这显然与“并发”是一样的。矛盾的。同时,不同的应用对于读一致性和事务隔离性的要求也不同。例如,许多应用程序对“不可重复读”和“幻读”并不敏感,可能更关心并发访问数据的能力。
MYSQL经常查看当前数据库的事务隔离级别:显示诸如'tx_isolation'之类的变量;
1。未分配读(Unallocated Read)
最低级别的隔离,允许其他事务看到未分配的数据将导致脏读。
2。提交读取
正在读取的数据可能会被其他事务修改,这可能会导致不可重复读取。 也就是说,读锁在事务读取时获取,读完后立即释放(无需等待事务完成),而写锁只有在事务提交后才释放。一旦读锁被释放,数据就可以被其他事务修改。该级别也是默认的 SQL Server 隔离级别。
3。可重复读取(Repeatable Read)
Select 获取到的所有数据都无法更改,以避免事务前后读取数据不一致。但是,幻读无法控制,因为其他事务当前无法修改所选数据,但可以对其进行添加。这意味着前一个事务有读锁,但没有卷锁。为什么称为可重复阅读水平?这是因为这个级别解决了下面的不可重复读问题。 (延伸:现在各大数据库都采用MVCC并发控制,使用后在隔离级别RR
(重复读)下不会出现幻读。)
MySQL默认值为REPEATABLE- READ
。
4。可串行化
所有事务都依次执行,以避免幻读。对于实现基于锁的并发控制的数据库,需要实现序列化。当您运行范围查询时,您必须获取范围锁。如果数据库没有实现基于锁的并发控制,当检测到批量违规事务时,必须回滚该事务。
5。摘要
- 读取未批准:当一笔交易尚未提交时,它所做的更改可以被其他交易看到。
- 读取确认:当交易被确认后,所做的更改将对其他交易可见。
- 可重复读取:事务执行期间可见的数据始终与事务开始时可见的数据一致。当然,在可重复的读隔离级别下,未提交的更改对于其他事务也是不可见的。
- 序列化:顾名思义,“写”会为同一行记录加“写锁”,“读”则会加“读锁”。当发生读写锁冲突时,后面访问的事务必须等待前一个事务完成后才能恢复执行。
四个级别逐渐提高,每个级别解决一个问题。交易级别越高,性能越差。大部分环境下(读已提交
可以使用)
作者:李红
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。