mysql 问题解决 3

4 事务

4、事务的并发问题?

事务的并发控制是为了解决多个事务同时运行时可能出现的问题。主要的并发问题包括:

  1. 丢失修改(Lost Update):是指在多个同时进行的并发事务中,一个事务的修改被另一个事务的修改覆盖,导致前一个事务的修改结果丢失。
  2. 脏读(Dirty Read):一个事务读取了另一个事务未提交的数据,如果那个事务回滚,读取的数据就是无效的。
    事务A从账户读取余额为$500并将其更新为$600,但还未提交。
    事务B读取了同一账户的余额,看到了$600。
    如果事务A回滚,事务B就读到了一个“脏”的数据,因为实际余额应该还是$500。
  3. 不可重复读(Non-repeatable Read):在同一个事务中,多次读取同一数据集合得到不同的结果,因为其他事务在两次读取之间修改了数据。
  4. 幻读(Phantom Read):是指在一个事务中,多次执行相同的查询语句,但返回的结果集却不同。通常情况下,幻读发生在并发事务中插入或删除数据时。
  5. 事务A查询所有余额大于$500的账户。
    事务B创建了一个新的账户,余额为$700,并提交了事务。
    事务A再次查询所有余额大于$500的账户时,发现有一个之前未见的新账户,即出现了幻读。

数据库通常通过锁定机制(如行锁、表锁、读/写锁等)和隔离级别(读未提交、读已提交、可重复读、序列化)来控制事务的并发,并尝试平衡并发性能与数据一致性之间的关系

6、事务的隔离级别有哪些?

不可重复读

在数据库中,不可重复读是一种并发控制问题,指的是在一个事务中多次读取同一数据时,得到的结果不一致。

下面是一个不可重复读的例子:

假设有一个银行账户表,其中包含了账户余额字段。假设有两个事务 T1 和 T2 同时进行。

  • T1 事务开始,读取账户 A 的余额为 1000 元。
  • T2 事务开始,将账户 A 的余额更新为 500 元。
  • T1 事务再次读取账户 A 的余额,得到的结果为 500 元,与第一次读取的结果不一致。

在这个例子中,T1 事务在执行过程中,由于 T2 事务对账户 A 的余额进行了更新,导致 T1 事务两次读取的结果不一致,这就是不可重复读问题。

数据库事务的隔离级别定义了一个事务可能受其他并发事务影响的程度。SQL标准定义了四个隔离级别:

  1. 读未提交(Read Uncommitted):事务可以读取其他未提交事务的数据。这是最低的隔离级别,在这个级别,所有的并发问题如脏读、不可重复读和幻读都可能发生。

    举例:如果事务A修改了一条记录但未提交,事务B可以读取这条“脏”的记录。如果事务A回滚,事务B读到的数据就是错误的。

  2. 读已提交(Read Committed):事务只能读取已经提交的事务的数据。这可以避免脏读。但是,不可重复读和幻读仍然可能发生。

    举例:事务A读取了一条记录,这时事务B修改了这条记录并提交。当事务A再次读取同一条记录时,会得到一个不同的结果。

举个在一个事务执行期间多次读取同一数据的例子
当一个事务在执行期间多次读取同一数据时,在可重复读(Repeatable Read)隔离级别下,这些读取的结果都应该是一致的,不会发生不可重复读的情况。以下是一个例子:

假设有一个银行数据库,包含了客户的账户信息。在可重复读隔离级别下,如果一个事务正在执行,它可能如下操作:

  1. 事务开始:事务 A 开始执行,它想要查询自己的账户余额。

  2. 第一次读取:事务 A 查询自己的账户余额,并获得结果。

  3. 事务 B 干预:同时,事务 B 也在执行,它转账给事务 A 一定金额的钱,从事务 B 的账户扣款。

  4. 第二次读取:事务 A 再次查询自己的账户余额,以确认转账是否已经生效。

  5. 可重复读(Repeatable Read):在这个级别,事务在整个过程中可以多次读取同样的数据行,并且保证结果一致,避免了不可重复读。但是,幻读仍然可能发生。

    举例:事务A读取满足某个条件的所有记录,这时事务B插入了一条新的满足条件的记录并提交。当事务A再次查询相同的条件,会发现有新的记录出现。

  6. 串行化(Serializable):这是最高的隔离级别,它通过锁定访问的数据行,来防止脏读、不可重复读和幻读,确保事务串行执行。

    举例:如果事务A在执行查询时,事务B想要插入、更新或删除影响到事务A查询范围的数据,那么它必须等待事务A完成后才能执行。

不同的数据库系统可能会以不同的方式实现这些隔离级别。提高隔离级别可以减少并发事务问题,但同时可能会增加等待时间和锁争用,影响数据库性能。因此,在实际应用中,通常需要在数据的完整性和系统性能之间做出权衡。

使用mysql的时候需要设置一下嘛?mysql默认的事务隔离级别是什么?

在使用MySQL时,可能需要根据应用程序的具体需求设置事务隔离级别。可以通过SQL语句在会话或全局级别设置隔离级别,如下所示:

-- 设置当前会话的隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL [desired level];

-- 设置全局默认的隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL [desired level];

其中 [desired level] 可以是:

  • READ UNCOMMITTED
  • READ COMMITTED
  • REPEATABLE READ
  • SERIALIZABLE

MySQL的默认事务隔离级别通常是REPEATABLE READ。在这个级别下,MySQL通过使用行级锁和一致性非锁定读取确保了可重复读,但在标准的SQL隔离级别中,幻读是可能的。然而,由于MySQL的InnoDB存储引擎使用了多版本并发控制(MVCC),在大多数情况下它实际上也可以防止幻读。

要查看当前MySQL会话或服务器的默认隔离级别,可以执行以下SQL查询:

-- 查看当前会话的隔离级别
SELECT @@tx_isolation;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值