mysql中数据库的并发事务问题
1.脏读(dirty-read):如果第二个事务查询到第一个事务还未提交的更新数据,就会形成脏读。
2.幻读/虚读(phantom read):一个事务执行两次,如果出现第二次事务执行比第一次多一些或少一些数据,造成两次查询结果不一致。可能是另一个事务在两个事务直接插入或删除一些数据造成的。
3.不可重复读():两次事务两次读取同一行数据,结果得到不同的状态结果,如果正好中间另一个事务更新了数据,两次结果相异,不可信任。
针对以上问题,通过设置事务隔离级别来解决。
以MYSQL数据库为例,事务隔离级别:
y:可以解决;n:不能解决
隔离级别 | 脏读 | 不可重复读 | 幻读 |
Read uncommotted(读未提交) | n | n | n |
Read committed(读提交) | y | n | n |
Repeatable read(可重复读取)(mysql默认) | y | y | n |
Serializable(可序化) | y | y | y |
隔离级别查看:
SELECT @@tx_isolation;
第一种隔离级别:Read uncommitted(读未提交)
如果一个事务已经开始写数据,则另外一个事务不允许同时进行写操作,但允许其他事务读此行数据,该隔离级别可以通过“排他写锁”,但是不排斥读线程实现。
特点:一写多读,写的时候,其他事务也能读
却可能出现脏读,也就是说事务B读取到了事务A未提交的数据,出现不可重复读问题,B同时读取了A提交前后某一行数据,数据不一致,也避免不了幻读问题,在此就不举例了。
第二种隔离级别:Read committed(读提交)
如果是一个读事务(线程),则允许其他事务读写,如果是写事务将会禁止其他事务访问该行数据,该隔离级别避免了脏读,但是可能出现不可重复读。事务A事先读取了数据,事务B紧接着更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。
特点:一个事务写这个表时,其它事务不可读,只能读写后的。
只解决了脏读问题
第三种隔离级别:Repeatable read(可重复读取)
可重复读取是指在一个事务内,多次读同一个数据,在这个事务还没结束时,其他事务不能访问该数据(包括了读写),这样就可以在同一个事务内两次读到的数据是一样的,因此称为是可重复读隔离级别,读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务(包括了读写),这样避免了不可重复读和脏读,但是有时可能会出现幻读(即一个事务在进行读某一行数据时,另一个事务对这行数据所在表进行了数据条数的增减,导致查询结果不一致)。(读取数据的事务)可以通过“共享读镜”和“排他写锁”实现。
特点:一个事务执行结束前,同一行数据只能在一个事务内读写,其他事务不能操作。
解决了脏读、不可重复读,但是还会出现幻读
第四种隔离级别:Serializable(可序化)
提供严格的事务隔离,它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行,如果仅仅通过“行级锁”是无法实现序列化的,必须通过其他机制保证新插入的数据不会被执行查询操作的事务访问到。序列化是最高的事务隔离级别,同时代价也是最高的,性能很低,一般很少使用,在该级别下,事务顺序执行。
特点:只能一个事务来读写这个表,其他事务没有读写权限。
不仅可以避免脏读、不可重复读,还避免了幻读
补充:以上四种级别,在实际效率方面,由高到低,也就是说安全级别高,也会导致效率的下降
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具