1.事务
并发连接下考虑事务。
事务的本质是并发控制的单元,是用户定义的一个操作序列。这些操作要么都做,要么都不做,是一个不可分割的工作单位。
事务控制语句
ACID特性
原子性:要么都做,要走么都不做。在事务执行期间,对数据的修改操作会记录在undo log中,**如果事务回滚,MySQL会使用undo log中的信息来撤销这些修改操作。如果事务提交,undo log中的信息将被保留,以便在后续的事务中使用。**在InnoDB中,undo log是由多个undo log段组成的。每个undo log段都是一个固定大小的文件,用于存储undo log中的一部分信息。当一个undo log段已经被使用完毕时,InnoDB会自动创建一个新的undo log段,以继续存储undo log中的信息。
一致性:从一种一致性状态到另一种一致性状态。
隔离性:MySQL中的事务隔离性是通过锁和MVCC(多版本并发控制)机制来实现的。
MySQL还使用MVCC机制来实现事务隔离性。MVCC机制允许多个事务同时访问同一行数据,每个事务看到的数据版本不同,从而实现了事务隔离性。在MySQL中,每个数据行都有一个版本号,当一个事务对该行数据进行修改时,会生成一个新的版本号。其他事务在读取该行数据时,会根据自己的事务版本号来读取相应的数据版本,从而实现了事务隔离性。
在MySQL中,事务隔离级别包括读未提交、读已提交、可重复读和串行化。不同的隔离级别会使用不同的锁和MVCC机制来实现事务隔离性。例如,读未提交隔离级别不会对数据进行任何锁定或版本控制,而串行化隔离级别会对所有的数据行进行写锁定,以保证事务的完全隔离性。
总之,MySQL中的事务隔离性是通过锁和MVCC机制来实现的。锁机制用于保证数据的一致性和隔离性,MVCC机制用于实现事务的并发控制和隔离性。在MySQL中,事务隔离级别可以通过设置来控制不同的隔离级别,以满足不同的应用场景和需求。
持久性:在MySQL中,redo log(重做日志)是用于保证事务持久性的一种日志。redo log记录了对数据的修改操作,以便在数据库崩溃或重启后恢复数据的一致性。
在事务执行期间,对数据的修改操作将被记录到redo log中。如果事务提交,redo log中的信息将被写入磁盘,以保证数据的持久性。如果数据库崩溃或重启,MySQL会使用redo log中的信息来恢复数据的一致性。
redo log的工作原理是将修改操作记录到一个环形缓冲区中,称为redo log缓冲区。当缓冲区被写满时,MySQL会将缓冲区中的信息写入磁盘,并将缓冲区清空,以便继续记录后续的修改操作。为了保证数据的持久性,MySQL还会将redo log缓冲区中的信息定期写入磁盘,以便在数据库崩溃或重启时使用。
在MySQL中,redo log是由多个redo log文件组成的。每个redo log文件都是一个固定大小的文件,用于存储redo log中的一部分信息。当一个redo log文件已经被使用完毕时,MySQL会自动创建一个新的redo log文件,以继续记录redo log中的信息。
总之,redo log是MySQL中用于保证事务持久性的一种日志。redo log记录了对数据的修改操作,以便在数据库崩溃或重启后恢复数据的一致性。在MySQL中,redo log是由多个redo log文件组成的,每个文件都是一个固定大小的文件,用于存储redo log中的一部分信息。
一个SQL语句是怎么执行的?
InnoDB:一个单个SQL语句就是一个事务。
隔离级别
目的:提升并发性能
1.读未提交:读到了其他事务还没提交的数据。在read uncommitted隔离级别下,事务可以读取到其他未提交的事务所修改的数据,这被称为脏读(dirty read)。这种隔离级别的优点是读取性能高,缺点是可能会读取到不一致的数据,因为其他事务的修改可能会被回滚。
2.读已提交:事务只能读取到已经提交的事务所修改的数据,这避免了脏读的问题。但是,由于其他事务可能会提交或回滚,因此在同一个事务内多次读取同一个数据可能会得到不同的结果,这被称为不可重复读(non-repeatable read)
3.可重复读: 当事务读取数据时,MySQL会记录一个事务开始的时间戳,并使用该时间戳来确定事务可以读取的数据版本。在同一个事务内多次读取同一个数据时,MySQL会始终返回相同的结果,即使其他事务在读取期间提交或回滚。这就是repeatable read的含义,即事务可以重复读取相同的数据而不会得到不同的结果。
不是,幻读不同于不可重复读。不可重复读是指在同一个事务内多次读取同一个数据时,可能会得到不同的结果,因为其他事务在读取期间提交或回滚。而幻读是指在同一个事务内多次查询同一个范围的数据时,可能会得到不同的结果,因为其他事务在这个范围内插入了新的数据。
例如,假设一个事务在执行如下的查询语句:
SELECT * FROM table WHERE column BETWEEN 10 AND 20;
如果在这个事务执行查询的过程中,另一个事务插入了一条符合条件的新数据,那么第一个事务在后续的查询中可能会返回这条新数据,这就是幻读。
为了避免幻读的问题,MySQL会使用间隙锁(gap lock)来锁定事务读取的数据范围,从而避免其他事务在这个范围内插入新的数据。但是,使用间隙锁会增加锁的开销,因此在一些特定的场景下,可以考虑使用其他的隔离级别来避免幻读的问题。例如,在Serializable隔离级别下,MySQL会对整个表进行锁定,从而避免幻读的问题。
脏读,不可重复读,幻读的总结
-
脏读:脏读只会在read uncommitted隔离级别下发生。在这个隔离级别下,一个事务可以读取到另一个未提交的事务所修改的数据,因此可能会读取到无效的数据。
-
不可重复读:不可重复读可能在read committed、repeatable read和serializable隔离级别下发生。
- 在read committed隔离级别下,一个事务只能读取到已经提交的事务所修改的数据。因此,如果一个事务在读取数据时,另一个事务修改了该数据并提交了事务,那么第一个事务在随后的读取中会得到不同的结果,这就是不可重复读。
- 在repeatable read隔离级别下,一个事务在读取数据时,会创建一个一致性视图(consistent snapshot),用于保证在整个事务过程中,读取到的数据是一致的。因此,如果一个事务在读取数据时,另一个事务修改了该数据并提交了事务,那么第一个事务在随后的读取中仍然会读取到原始的数据,不会发生不可重复读。
- 在serializable隔离级别下,一个事务在读取数据时,会对整个表进行锁定,从而避免并发事务的干扰。因此,不可重复读和幻读都不会发生。
- 幻读:幻读只会在repeatable read和serializable隔离级别下发生。
- 在repeatable read隔离级别下,虽然一个事务在读取数据时,会创建一个一致性视图,用于保证在整个事务过程中,读取到的数据是一致的。但是,如果一个事务在查询一个范围的数据时,另一个事务插入了符合条件的新数据并提交了事务,那么第一个事务在随后的查询中会得到不同的结果,这就是幻读。
- 在serializable隔离级别下,一个事务在读取数据时,会对整个表进行锁定,从而避免其他事务的干扰。因此,幻读也不会发生。
需要注意的是,隔离级别越高,数据的一致性和安全性越高,但是并发性能越差。因此,在选择事务隔离级别时,需要根据具体的应用场景进行权衡和选择。