赞
踩
好文推荐:
2.5万字详解23种设计模式
springboot 实现延时队列(超级实用)
2.5万字讲解DDD领域驱动设计
MySQL事务是指一系列数据库操作(例如INSERT、UPDATE、DELETE等)被作为一个单独的执行单元来执行的过程。事务可以确保数据库在并发环境下的数据一致性和完整性,并支持原子性、一致性、隔离性和持久性的特性(也称为ACID特性)。
原子性(Atomicity):事务是一个原子操作单元,要么全部执行成功,要么全部失败回滚。如果事务中的任何一个操作失败,则整个事务将被回滚到初始状态。
一致性(Consistency):事务在执行之前和执行之后,数据库的状态必须保持一致。这意味着事务将从一个一致的状态转换到另一个一致的状态,确保数据的完整性。
隔离性(Isolation):每个事务的执行都应该与其他事务相互隔离,使它们彼此独立。事务的隔离性确保并发执行的事务不会相互干扰,从而防止数据损坏或不一致。
持久性(Durability):一旦事务提交成功,其所做的更改将永久保存在数据库中,即使在系统故障或重启后也能够恢复。持久性确保事务的结果能够长期存储,以便供后续读取和使用。
两个事务都是读操作不会有并发问题,只有在读写或者写写场景下,就有并发问题了,后面会通过实战复现一下四种问题。
脏读:在读读场景下,一个事务读取了另一个未提交(或已回滚)事务的数据。如果读取到的数据最终不会被提交,那么本次读取就是脏读。
不可重复读:在读写(update)场景下,同一个事务内,多次读取同一行数据时,得到了不同的结果。这是由于其他事务在读取期间修改了数据造成的。
幻读:在读写(insert)场景下,一个事务读到另一个事务已提交的新插入的数据。其实这样的说法并不准确,严谨来说是在repeatable read隔离级别下,只有在当前读的情况下,才会有幻读问题,在快照读的情况下,是没有幻读问题的。什么是当前读,什么是快照读,下文会结合实例一一讲解。
更新丢失:在写写(update)场景下,两个事务同时读取同一行数据,并且同时进行修改。由于事务隔离级别的不同或执行顺序的不同,其中一个事务的修改可能会覆盖另一个事务的修改,导致更新丢失。
事务隔离级别是数据库管理系统(DBMS)提供的一种机制,用于控制并发事务之间的可见性和相互影响程度。MySQL 支持四种事务隔离级别:
事务隔离级别 脏读 不可重复读 幻读
read uncommitted: 否 否 否
read committed : 是 否 否
repeatable read: 是 是 否
serializable: 是 是 是
SELECT @@tx_isolation;
set session transaction isolation level read uncommitted;
set session transaction isolation level read committed;
set session transaction isolation level repeatable read;
set session transaction isolation level serializable;
BEGIN;
COMMIT;
ROLLBACK;
将事务隔离级别设置为:read uncommitted
-- 查看当前会话的事务隔离级别
select @@tx_isolation;
-- 设置当前会话的隔离级别
set session transaction isolation level read uncommitted;
-- 开启事务
begin;
select * from student;
查询结果:
-- 查看当前会话的事务隔离级别
select @@tx_isolation;
-- 设置当前会话的隔离级别
set session transaction isolation level read uncommitted;
-- 开启事务
begin;
update student set age = 28 where id = 1;
-- 查看当前会话的事务隔离级别
select @@tx_isolation;
-- 设置当前会话的隔离级别
set session transaction isolation level read uncommitted;
-- 开启事务
begin;
select * from student;
查询结果:
将事务隔离级别设置为:read committed,虽然解决了脏读,但是存在不可重复读
-- 查看当前会话的事务隔离级别
select @@tx_isolation;
-- 设置当前会话的隔离级别
set session transaction isolation level read committed;
-- 开启事务
begin;
select * from student;
查询结果:
-- 查看当前会话的事务隔离级别
select @@tx_isolation;
-- 设置当前会话的隔离级别
set session transaction isolation level read committed;
-- 开启事务
begin;
update student set age = 19 where id = 1;
commit;
select @@tx_isolation; #查看当前会话的事务隔离级别
set session transaction isolation level read committed; #设置当前会话的隔离级别
begin; #开启事务
select * from student #查询数据
查询结果:
将事务隔离级别设置为:repeatable read,可以解决脏读和重复读
-- 查看当前会话的事务隔离级别
select @@tx_isolation;
-- 设置当前会话的隔离级别
set session transaction isolation level repeatable read;
-- 开启事务
begin;
select * from student;
查询结果:2. 事务B:插入一条数据,并提交事务
-- 查看当前会话的事务隔离级别
select @@tx_isolation;
-- 设置当前会话的隔离级别
set session transaction isolation level repeatable read;
-- 开启事务
begin;
INSERT INTO student (id, name, age) VALUES(3, '刘备', 38);
commit;
-- 查看当前会话的事务隔离级别
select @@tx_isolation;
-- 设置当前会话的隔离级别
set session transaction isolation level repeatable read;
-- 开启事务
begin;
select * from student;
快照读是MVCC的核心特性之一。
-- 查看当前会话的事务隔离级别
select @@tx_isolation;
-- 设置当前会话的隔离级别
set session transaction isolation level repeatable read;
-- 开启事务
begin;
select * from student for update;
-- 查看当前会话的事务隔离级别
select @@tx_isolation;
-- 设置当前会话的隔离级别
set session transaction isolation level repeatable read;
-- 开启事务
begin;
INSERT INTO student (id, name, age) VALUES(3, '刘备', 38);
commit;
-- 查看当前会话的事务隔离级别
select @@tx_isolation;
-- 设置当前会话的隔离级别
set session transaction isolation level repeatable read;
-- 开启事务
begin;
select * from student for update;
结果如下:
大事务问题通常涉及对数据库中大量数据进行处理的事务,这些事务可能导致性能下降、锁冲突或事务执行时间过长。
假设有一个下单的应用场景,每当用户提交订单时,系统会执行以下操作:
①创建一个新订单记录
②从用户购物车中删除已购买的商品
③更新商品库存。
现在,假设有一天,你的网站举办了一个促销活动,吸引了大量用户同时下订单。这导致了大量的 “订单处理” 事务同时运行,每个事务都要对订单和库存进行操作。
大量订单处理事务同时运行可能会导致以下问题:
①锁冲突:多个事务同时尝试修改相同的订单或商品库存,导致锁定和等待。
②性能下降:大量的数据库操作可能导致数据库性能急剧下降。
③事务超时:事务执行时间过长,导致超时问题。
解决目标就是,缩短事务执行时间,提高性能
解决方法:
①事务拆分:
将大事务拆分成多个小事务,每个小事务只处理一个订单或一组相关订单。
这可以减小每个事务的范围,减少锁冲突和提高并发性。
②使用乐观锁:
使用乐观锁机制来处理商品库存更新。每个事务在更新库存之前检查库存是否足够,如果不够就回滚事务。
这可以避免大规模的锁冲突。
③使用消息队列:
将订单处理任务放入消息队列,然后由后台任务异步处理。
这将减轻数据库的压力,并允许系统在非高峰时段处理订单。
⑤性能优化:
优化数据库表结构和索引以提高查询性能。
使用数据库缓存来减少重复查询。
⑥定期清理历史数据:
定期清理订单和日志数据,以减少数据库负担。
如果看到这里,说明你喜欢这篇文章,请关注和点赞小编。关注【微信公众号微信】搜索【老板再来一杯时光】回复【进群】即可进入无广告交流群!回复【java】即可获取【java基础经典面试】一份!
好文推荐:
2.5万字详解23种设计模式
springboot 实现延时队列(超级实用)
2.5万字讲解DDD领域驱动设计
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。