【mysql】mysql事务详解

一、事务

1、事务的定义

事务即 (transaction) ,是数据库系统区别于文件系统的重要特性之一。在文件系统中,如果我们正在写文件,但是操作系统崩溃了,那么文件中的数据可能会丢失。但是数据库可以通过事务机制来确保这一点。

2、使用事务的目的

事务会把数据库从一中状态转换为另一种状态。在数据库提交工作时,可以确保要么所有工作都已经保存了,要么所有修改都不保存。

3、事务的四大特性

  • 原子性(atomicity)
    所谓原子性,是指整个数据库的每个事务都是不可分割的单位。只有事务中的所有 SQL 语句都执行成功,才算整个事务成功,事务才会被提交。如果事务中任何一个 SQL 语句执行失败,整个事务都应该被回滚。
    场景:如在银行取款机取款,要么取款成功、要么取款失败。不能存在卡里钱扣了,取款机并没有出金额;或者钱取到了,但是卡里并没有减去该金额。
  • 一致性(consistency)
    所谓一致性,是指将数据库从一种一致性状态转换为下一种一致性状态。不允许数据库中的数据出现新老数据都有的情况,要么都是老数据,要么都是新数据。用更书面化的表达就是:数据的完整性约束没有被破坏。
    场景:如在一个用户表中,存在一个身份证号的字段,且身份证号满足唯一约束条件;如果一个事务对身份证号进行了修改,在事务进行提交或回滚后,身份号信息变的不具有唯一性了,这就破坏了事务的一致性。
  • 隔离性(isolation)
    所谓隔离性,是指一个事务的影响在该事务提交前对其他事务都不可见,它通过锁机制来实现。
    场景:多个并行交叉的事务间的操作可以相互分离,即多个事务对于其他事务不可见。
  • 持久性(durability)
    所谓持久性,是指事务一旦被提交,其结果就是永久性的。即使发生宕机等故障,数据库也能将数据恢复。
    场景:事务提交后,所有变化都是永久的,即使数据库崩溃而需要恢复时也能保证恢复后提交的数不会丢失。

4、事务操作

事务的语法

  1. 在 MySQL 命令行的默认设置下,事务是自动提交的,即执行了SQL 语句之后会马上执行 commit 操作,我们可以设置 set autocommit=0 来禁用当前回话的自动提交。
  2. 还可以用 begin 、start transaction 来显式的开始一个事务。
  3. commit 在默认设置下是等价于 commit work 的,表示提交事务。
  4. rollback 在默认设置下等价于 rollback work,表示事务回滚。
  5. savepoint xxx 表示定义一个保存点,在一个事务中可以有多个保存点。
  6. release savepoint xxx 表示删除一个保存点,当没有该保存点的时候执行该语句,会抛出一个异常。
  7. rollback to [savepoint] xxx 表示回滚到某个保存点。

–查询事务自动提交状态

mysql> show variables like '%autocommit%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    |  ON   |
+---------------+-------+
1 row in set (0.00 sec)

mysql> ##--局部修改
mysql> set session autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> show global variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | OFF   |
+---------------+-------+
1 row in set (0.00 sec)

在这里插入图片描述
通过上面,我们可以感受到事务的隔离性,也就是两个事务之间并不知道对方的存在,在 MySQL 的默认隔离级别下,当一个事务还没有提交的时候,其他事务是无法感知到数据的变化的。
在这里插入图片描述
当事务提交后即可看到另一个事务修改的结果。

5、事务隔离级别

事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。 在并发下事务会容易出现一些问题

***脏读 *** :一个事务开始读取了某行数据,另外一个事务已经更新了此数据但没有能够及时提交。这是相当危险的,因为很可能所有的操作都被回滚。
不可重复读:一个事务对同一行数据重复读取两次,但是却得到了不同的结果。例如,在两次读取的中途,有另外一个事务对该型数据进行了修改,并提交。
幻读:事务在操作过程中进行两次查询,第二次查询的结果包含了第一次查询中未出现的数据(SQL不一定一样)。这是因为在两次查询过程中有另外一个 事务插入数据

在MySQL中存在(InnoDB)事务存在着4中隔离级别,不同的隔离级别对事务的处理不同。

未授权读取(未提交读 Read Uncommitted):READ-UNCOMMITTED | 0:存在脏读,不可重复读,幻读的问题。如果一个事务已经开始写数据,则另外一个数据则不会允许同时进行写操作,但允许其他事务读此行数据。隔离级别可以通过“排他写锁”实现。
授权读取(已读提交 Read committed):READ-COMMITTED | 1:解决脏读的问题,存在不可重复读,幻读的问题。这个可以通过“排他写锁”实现。读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。
可重复读取(Repeatable Read):REPEATABLE-READ | 2:解决脏读,不可重复读的问题,存在幻读的问题,默认隔离级别。可通过“共享锁”,“排他锁”实现。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。
序列化(Serializable):SERIALIZABLE | 3:解决脏读,不可重复读,幻读,可保证事务安全,但完全串行执行,性能最低。提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,不能并发执行。如果仅仅通过“行级锁”是无法实现事务序列化的,必须要通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。

  • 事务隔离级别查看和设置
###这是mysql默认的隔离级别
mysql> SHOW VARIABLES LIKE '%transaction_isolation%';
+-----------------------+-----------------+
| Variable_name         | Value           |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.00 sec)

我们可以通过如下方式设置数据库的隔离级别

-- 设定全局的隔离级别 设定会话 global 替换为 session 即可 把set语法温习一下
-- SET [GLOABL] config_name = 'foobar';
-- SET @@[session|global].config_name = 'foobar';
-- SELECT @@[global.]config_name;
--全局修改
SET @@gloabl.transaction_isolation = 0;
SET @@gloabl.transaction_isolation = 'READ-UNCOMMITTED';
SET @@gloabl.transaction_isolation = 1;
SET @@gloabl.transaction_isolation = 'READ-COMMITTED';
SET @@gloabl.transaction_isolation = 2;
SET @@gloabl.transaction_isolation = 'REPEATABLE-READ';
SET @@gloabl.transaction_isolation = 3;
SET @@gloabl.transaction_isolation = 'SERIALIZABLE';
--局部修改
SET @@session.transaction_isolation = 0;
SET @@session.transaction_isolation = 'READ-UNCOMMITTED';
SET @@session.transaction_isolation = 1;
SET @@session.transaction_isolation = 'READ-COMMITTED';
SET @@session.transaction_isolation = 2;
SET @@session.transaction_isolation = 'REPEATABLE-READ';
SET @@session.transaction_isolation = 3;
SET @@session.transaction_isolation = 'SERIALIZABLE';
  • 事务隔离级别的实现
    未授权提交(未提交读 Read UNCommitted):主要在于重做和回滚-共享锁 在事务进行中,允许其他事务可以读取修改的数据。
    授权提交():使用了排它锁,不允许其他事务读取到数据,同时也不能修改
    可重复读取:排它锁,会把可读取的数据放在缓存区中,而其他事务修改的数据会加一把锁
    序列化:串行化,实现不仅仅只是靠行锁,还会加上其他机制实现

  • 事务日志生成流程

在这里插入图片描述
Innodb的一条事务日志共经历4个阶段:
1)创建阶段:事务创建一条日志;
2)日志刷盘:日志写入到磁盘上的日志文件; (ib_logfile里面)
3)数据刷盘:日志对应的脏页数据写入到磁盘上的数据文件;
4)写CKP:日志被当作Checkpoint写入日志文件;(ib_data里面)

  • 日志文件生成模式
mysql> show variables like '%innodb_flush_log_at_tr%';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 1     |
+--------------------------------+-------+
1 row in set (0.00 sec)

该模式可设置0、1、2三个值各表示的含义如下图

在这里插入图片描述


我们江湖再见。。。。。。。。。

猜你喜欢

转载自blog.csdn.net/Qcg0223/article/details/108238197