首页 > 技术文章 > MySQL的事务相关概念

storyawine 2020-08-05 21:08 原文

MySQL的事务相关概念

我们可以把事务理解为一组sql语句的集合,事务可以只包含一条sql语句,也能包含多条复杂的SQL语句,事务中的所有SQL语句被当作一个操作单元,也就是说,事务中的SQL语句要么都执行成功,要么全部执行失败,事务内的SQL语句被当做一个整体,被当做一个原子进行操作。
mysql中,innodb是支持事务的,而且完全符合ACID特性:
A:原子性
C:一致性
I:隔离性
D:持久性
 
 事务日志:
 redo log概述:
redo log是物理日志,是因为redo log中记录的是数据库对页的操作,而不是逻辑上的增删改查,redo log具有等幂性。
 
undo log概述:
  
事务日志参数:
mysql> show variables like '%innodb%log%';
+-----------------------------------+----------------------------+
| Variable_name                     | Value                      |
+-----------------------------------+----------------------------+
| innodb_api_enable_binlog          | OFF                        |
| innodb_cdb_log_checksum_algorithm | innodb                     |
| innodb_flush_log_at_timeout       | 1                          |
| innodb_flush_log_at_trx_commit    | 2                          |
| innodb_locks_unsafe_for_binlog    | OFF                        |
| innodb_log_buffer_size            | 67108864                   |
| innodb_log_compressed_pages       | ON                         |
| innodb_log_file_size              | 536870912                  |
| innodb_log_files_in_group         | 2                          |
| innodb_log_group_home_dir         | /data/mysql_root/log/20143 |
| innodb_mirrored_log_groups        | 1                          |
| innodb_online_alter_log_max_size  | 134217728                  |
| innodb_undo_logs                  | 128                        |
+-----------------------------------+----------------------------+
innodb_log_file_size:表示每个redo log文件的大小,上面展示的是512M,有点大了!
innodb_log_files_in_group:表示日志组里有几个redo log文件
innodb_log_group_home_dir:表示重做日志的路径,默认情况下是在/var/lib/mysql下的:
256M -rw-rw----. 1 mysql mysql 256M Sep 11 20:34 ib_logfile0
256M -rw-rw----. 1 mysql mysql 256M May 17 20:46 ib_logfile1
这两个文件!
innodb_mirrored_log_groups:表示一共有几组日志组,这里看出来只有一组!
innodb_flush_log_at_trx_commit:此值表示当事务提交后,是否立即将redo log从内存中写入到redo log file中;此值默认值为1,表示当事务提交时必须将redo log从内存中写入到磁盘中,此值为1时,满足ACID要求!
如果设置为0:事务提交时不会把内存中日志写入到磁盘,但是会每秒自动写入一次。
如果设置为2:表示有事务提交时,只会把redo log写入到文件系统内存中(os buffer),但不会立即写入到磁盘中,而是每秒从文件系统缓存中写入到磁盘,此值为2时,如果只是mysql数据库宕机,但是操作系统没有宕机,则数据不会丢失,如果操作系统宕机,重启mysql之后会丢失未从文件系统中写入到磁盘的事务信息(约一秒钟)。
此值设置为1:安全性高,性能最低;
设置为0:性能最高,安全性最低;
设置为2:性能较高,安全性较低。
具体根据业务情况而定!
 
事务控制语句:
在MySQL中,我们每执行一条SQL,mysql都会把这条SQL当做一个单独语句事务去执行,而且默认是自动提交的,我们使用如下语句查看是否启动了自动提交:
mysql> show variables like '%autocommit%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
这里看到是打开的,表示执行SQL语句以后会自动提交,如果想要手动控制提交操作,则需要显示的开始一个事务,或者禁用自动提交功能(set autocommit=0),进行手动提交。
先看下事务控制语句:
start transaction或者begin:表示显示的开始一个事务,但是在存贮过程中,mysql会将begin识别为begin...end,所以在存储过程中只能使用start transaction来开始事务。
commit或者commit work:表示提交事务,也就是从begin到commit之间的所有SQL都是一个事务中的。
rollback或者rollback work:表示回滚事务,回滚事务会撤销所有未提交的修改并结束当前事务。
savepoint标识符:表示创建一个事务的保存点,以便我们回滚到当前的保存点,而不是回滚整个事物,就像你创建的快照一样!
rollback to savepoint:表示根据标识符回滚到指定的保存点,rollback to savepoint并不会结束当前事务,与rollback不同!
release savepoint标识符:表示删除一个保存点。
 
事务隔离级别:
四种隔离级别:
可重复读:
不管事务1是否提交,只要事务2没有提交,那么事务1做的改变,就不会被事务2看到,因此这条数据在事务2中是可以被重复读到的!
思考:事务隔离是由锁来实现的,在事务1进行更新语句时,会对数据施加写锁,但是在事务2中仍然可以查询操作,可写锁是排它锁,为什么事务2还能读?
因为innodb采用了一种‘一致性非锁定读’机制提高了数据库的并发性,他的功能是如果当前行被施加了排它锁,那么当需要读取该行数据时,则不会等待行上的锁释放,而是读取一个快照数据,这个快照也即是之前版本的数据,即历史数据!
并不是所有的隔离级别都使用了一致性非锁定读,在可重复读和读提交的隔离级别下,能够使用,但是在这两个级别中对快照的定义又不同,因此也会出现不同的现象,可重复读的快照,是在事务2开始的时候,当前的行数据,那么在整个过程中,事务2都只会读到开始时的数据。
 
可重复读会出现‘幻读’的情况:
(这里借用朱双印博客中的一段截图说明幻读)
 
串行化:
同时开启两个事务,当事务1执行的更新语句,此时事务2是查询不了该表的,因为事务1会施加一个写锁,因此事务2对该表的读请求会被阻塞。
 
读提交:
同时开启两个事务,事务1做的改动,在没提交的情况下,事务2看不到,当事务1提交了,事务2在没提交的情况下,也能看到;
这样就会出现不可重复读以及幻读的问题,比可重复读的问题更多,但是并发性更高!
 
读未提交:
同时开启两个事务,事务1只要多了数据更新,不管有没有提交,事务2也不关有没有提交,他都能看到更新后的数据!
当前事务能够看到被的事务中没有提交的数据,我们称之为‘脏读’!
当隔离级别处于读未提交的时候,其并发性是最强的,但是隔离性和安全性是最差的!
 
以上就是不同隔离级别的特点!

 

推荐阅读