当前位置: 首页 > 科技观察

本文阐明MySQL事务隔离级别

时间:2023-03-16 20:44:36 科技观察

业务系统在运行时,往往有多个线程同时操作数据库,而MySQL也需要对多个请求进行多线程处理,那么多条SQL语句如何在每笔交易执行?基本上就是将数据页从磁盘加载到BufferPool的缓存页,然后更新BufferPool中的缓存页,同时记录redolog和undolog。当多个线程并发执行时,会出现一些问题:多个事务并发执行,可能会更新缓存页中的同一行数据。如何解决这个冲突?一些事务正在更新一行数据,而另外一个事务正在查询这行数据。如何解决这个冲突?接下来要讨论的内容主要包括多事务并发操作的问题,MySQL的事务隔离级别,MVCC多版本控制,锁。脏读事务1读取事务2更新的数据,然后事务2回滚操作,则事务1读取的数据为脏数据。比如:张三的工资是8000,现在领导要涨到10000。事务1将他的工资改成了10000,但是事务还没有提交。事务2正在读取张三的工资,唯一的10000。此时事务1回滚,张三的工资又变成了8000。事务2把张三的工资10000读成了脏数据,事务2做了脏读。不可重复读事务1多次读取同一个数据,事务2在多次读取事务1的过程中更新并提交数据,导致事务1多次读取同一个数据结果不一致。例如:事务1,读取张三的工资为8000。事务2,将张三的工资改为10000,提交事务。交易1,再次读取张三的工资,此时工资为10000。在一个事务中两次读取相同数据的结果是不同的,即不可重复读。幻读一个事务,用同一个SQL多次查询,每次查询都会找到一些以前没有见过的数据。比如现在公司有10个人8000的工资。事务1,读取所有工资为8000的10个人。事务2,插入一条工资为10000的记录。事务1再次读取工资为8000的11个人。这时候,交易1出现了幻觉。同样的SQL查询语句第一次查到10个人,第二次查到11个人。不可重复读和幻读很容易混淆。不可重复读重在修改,幻读重在增删改查。解决不可重复读只需要对满足条件的行进行加锁,解决幻读需要对表进行加锁。脏读、不可重复读、幻读、数据库并发执行,每个线程都可能开启一个事务,每个事务都会进行crud操作。数据库并发执行多个事务,多个事务并发CRUD缓存页中的同一批数据,可能会导致脏读、不可重复读、幻读等问题。所以,这些问题的本质都是数据库的多事务并发问题。为了解决这些问题,数据库设计了事务隔离级别、MVCC多版本控制、锁机制。事务隔离级别SQL标准定义了四种事务隔离级别,即事务并发运行时如何相互隔离,MySQL默认为可重复读(RR)。不同的隔离级别可以避免不同的事务并发问题。可能会发生未提交读(RU)、脏读、不可重复读和幻读。对于读提交(RC),不会出现脏读,但会出现不可重复读和幻读。换句话说,你无法读取事务未提交时修改的值。但是,事务一旦提交,你的事务就可以读到它,所以你多次读到的值可能不一样。Repeatable-read(RR),MySQL默认的事务隔离级别,为解决脏读、不可重复读、幻读等问题做了很多复杂的工作。通常,这种隔离级别可以用于生产环境。serializable,事务是串行执行的,根本不会并发执行,所以不会出现脏读、不可重复读、幻读等问题。但是缺点也很明显,就是并发性太差。一般生产环境不会用