并行事务会引发什么问题?
同时处理多个事务的时候,就可能出现脏读(dirty read)、不可重复读(non-repeatable read)、幻读(phantom read)的问题。
脏读:
如果一个事务「读到」了另一个「未提交事务修改过的数据」,就意味着发生了「脏读」现象。
- 例子:事务A开始并读取某账户余额为1000元。此时,事务B开始,将该账户余额改为1500元但尚未提交。如果事务A再次读取该账户余额,它可能会看到1500元,这是事务B未提交的数据。如果事务B最终回滚,事务A读取的数据就是脏数据。
不可重复读:
在一个事务内多次读取同一个数据,如果出现前后两次读到的数据不一样的情况,就意味着发生了「不可重复读」现象
- 例子:事务A读取了一个商品的库存数量为100。此时,事务B开始,购买了10个商品,减少了库存数量但尚未提交。如果事务A再次查询该商品的库存数量,它会发现数量变为90,与之前的读取结果不同。
幻读:
在一个事务内多次查询某个符合查询条件的「记录数量」,如果出现前后两次查询到的记录数量不一样的情况,就意味着发生了「幻读」现象。
- 例子:事务A执行了一个查询,统计某个商品类别下的总商品数,假设得到结果为10。此时,事务B开始,向该类别添加了多个新商品,但尚未提交。如果事务A再次执行相同的查询,它可能会得到一个不同的结果,比如15,即使它没有读取到B事务添加的具体商品记录,但总数已经改变。
事务的隔离级别有哪些?
隔离级别定义了事务之间如何相互隔离,以避免并发事务带来的数据不一致问题,如脏读、不可重复读和幻读
SQL 标准提出了四种隔离级别来规避这些现象,隔离级别越高,性能效率就越低,这四个隔离级别如下:
- 读未提交(read uncommitted),指一个事务还没提交时,它做的变更就能被其他事务看到;
- 读提交(read committed),指一个事务提交之后,它做的变更才能被其他事务看到;
- 可重复读(repeatable read),指一个事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,MySQL InnoDB 引擎的默认隔离级别;
- 串行化(serializable );会对记录加上读写锁,在多个事务对这条记录进行读写操作时,如果发生了读写冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行;
MySQL InnoDB 引擎的默认隔离级别虽然是「可重复读」,但是它很大程度上避免幻读现象
参考:小林coding