1.事务的含义:
事务可以简单理解为一组操作,这些操作要么一起成功执行,要么都不执行。就像一个完整的任务,如果这个任务的一部分失败了,整个任务都要放弃。这样做的目的是为了确保数据的一致性和完整性。
2.Mysql事务的特性:
原子性:事务中所有的操作要么一起成功,要么全一起失败。
一致性:事务在执行前后 ,数据库的数据要跟结果始终保持一致。
隔离性:一个事务请求统一数据,多个事务同时进行时,互不影响。
持久性:一旦事务成功提交,其结果是永久生效的,不会因为系统故障而丢失。
事务就像一个整体的工作任务,确保每一步都正确完成,才能算这个任务成功,避免中途出错导致的问题
3.事务的并发问题:
1. 脏读(Dirty Read)
定义:脏读是指一个事务读取了另一个事务未提交的修改。在这种情况下,如果被读取的事务回滚,那么读取到的数据就是不一致的。
示例:
事务A更新了一条记录,将price从100改为200,但事务A尚未提交。
同时,事务B读取了这条记录的数据,此时事务B看到的price是200。
如果事务A之后回滚,那么事务B读取的200就是一个脏读,因为这条记录最终并不存在。
2. 不可重复读(Non-repeatable Read)
定义:不可重复读是指在同一事务中,读取同一数据记录的两次结果不相同。换句话说,如果一个事务在读取某个数据后,另一个事务对该数据进行了更新或删除,那么当第一个事务再次读取该数据时,结果会不同。
示例:
事务A执行时读取了用户的balance,假设是100。
随后,事务B对该用户的balance进行了更新,将其改为150并提交。
当事务A再次尝试读取该用户的balance时,看到的值是150,而不是之前的100。这种情况就是不可重复读。
3. 幻读(Phantom Read)
定义:幻读是指在一个事务中,读取了一组数据的结果(例如SQL查询),在同一事务中再次读取时,结果集发生了变化(例如记录的数量变化),通常是因为其他事务进行了插入或删除操作。
示例:
事务A执行以下查询,返回了某个条件下的所有用户,假设有3个用户。
SELECT * FROM users WHERE age > 18;
事务B随后插入了一个新用户,满足上述查询条件,提交后。
当事务A再次执行相同的查询时,发现返回了4个用户,而不是之前的3个用户。这个新增的用户视为“幻影”,因为它在第一次查询时并不存在。
4. 事务的并发场景
1.读一读 :不存在任何问题
解释:
在两个事务都只是执行读操作的情况下(例如,事务 A 和事务 B 都只执行 SELECT 查询),不会存在任何问题。这是因为读取操作不会修改数据,因此无论是不同事务还是同一个事务多次读取,结果都是一致的。在这种情况下:
没有脏读:因为没有事务在输出未提交的数据。
没有不可重复读:因为没有写入数据。
没有幻读:因为没有插入新的数据行。
2.读一写 :有线程安全问题,脏读,幻读,不可重复读
解释:
在一个事务进行读操作时,另一个事务进行写操作时,可能会出现多种线程安全问题的相关性,尤其是脏读、不可重复读和幻读:
脏读(Dirty Read):事务 A 读取了事务 B 的未提交数据,如果事务 B 之后回滚,那么事务 A 就读取了一个无效的数据状态。
不可重复读(Non-repeatable Read):事务 A 在读取某行数据后,事务 B 对该行数据进行了更新。如果事务 A 再次读取同一行数据,可能会得到不同的结果。
幻读(Phantom Read):事务 A 在进行某个条件的查询时(如某个范围内的行),事务 B 在此期间插入了一行新数据。此时,事务 A 再次执行相同的查询,可能会得到新的记录,造成原有结果集的“幻觉”。
3.写一写 : 有线程安全问题,可能存在数据丢失
解释:
当两个事务都尝试对同一数据进行写操作时,会出现更严重的线程安全问题,导致数据不一致,甚至数据丢失的情况:
数据丢失:如果两个事务同时修改同一行数据,而都以某种方式完成(例如,一个事务的改变覆盖了另一个事务),这可能导致一个事务的结果被另一个事务覆盖,从而导致数据丢失。例如,事务 A 更新了某个字段,事务 B 也更新了同一个字段,最终结果可能只保留事务 B 的更改。
写冲突:由于两个写事务争夺对数据的控制,可能会导致事务提交失败或回滚的情况。
5.事务的隔离级别
读未提交 :允许一个事务读取另一个事务未提交的数据。这是最低的隔离级别,可能会导致“脏读”问题。
读已提交:一个事务只能读取已提交的事务所做的修改。这样可以防止“脏读”现象。
可重复读:在一个事务中,如果读取了某个数据,在事务结束之前再次读取该数据得到的结果不会改变。可以防止“脏读”和“不可重复读”现象,但仍然可能出现“幻读”。
串行化 :这是最高的隔离级别,强制所有事务完全串行执行。任何事务都无法开始,直到其他事务完成。这可以防止“脏读”、“不可重复读”和“幻读”现象。
6.事务的实现原理
MySQL 支持多个存储引擎,每个存储引擎具有不同的事务处理机制。最常用的存储引擎是 InnoDB,它为事务提供了全面的支持。
6.1 锁机制
- 行级锁:InnoDB 使用行级锁来提高并发性,只锁定被事务修改的行,而不是整个表。
- 表级锁:MyISAM 存储引擎使用表级锁,会锁定整个表,导致并发性较差。
- 多版本并发控制(MVCC):InnoDB 使用 MVCC 来实现高效的事务隔离。每个事务都有一个快照,可以在非锁定的情况下读取数据,避免了读锁和写锁的冲突。
6.2 日志管理
MySQL 使用两种日志来管理事务:
- 重做日志(Redo Log):记录已提交事务的所有改变,这是为了保证持久性。即使系统崩溃,重启后可以通过重做日志恢复到最新状态。
- 回滚日志(Undo Log):用来支持事务的回滚和实现原子性。当事务被回滚时,通过回滚日志来撤销已经执行的操作。
6.3 事务的操作
在 MySQL 中,常用的事务操作有:
- BEGIN / START TRANSACTION:开始一个新的事务。
- COMMIT:提交事务,生效所有在事务中的更改。
- ROLLBACK:回滚事务,撤销在事务期间所做的所有更改。