什么是事务?

当多个用户访问同一份数据时,一个用户在更改数据的过程中可能有其他用户同时发起更改请求,为保证数据库记录的更新从一个一致性状态更改为另一个一致性状态,这样的操作过程就是事务。事务具有的ACID属性:

    • 原子性(Atomicity):事务中所有的操作视为一个原子单元,即对于事务所进行的修改、删除等操作只能是全部提交或者全部回滚。
    • 一致性(Consistency):事务在完成操作后,必须使所用的数据从一种一致性状态变为另外一种一致性状态,所有的变更都必须应用于事务的修改,以确保数据的完整性。
    • 隔离性(Isolation):一个事务中的操作语句所做的修改必须与其他事务相隔离,在进行事务查看数据时数据所处的状态,要么是被另一个事务并发修改之前的状态,要么是修改之后的状态,即当前事务不会查看由另一个并发事务正在修改的数据。这种特性通过锁机制实现。
    • 持久性(Durability):事务完成之后,所做的修改对数据的影响是永久的,即使系统重启或者是出现故障数据仍可以恢复。

MySQL中提供多种事务型存储引擎,如InnoDB,BDB。但是MyISAM不支持事务,InnoDB支持事务、行级锁、高并发。

InnoDB事务实现原理:undo日志和redo日志,配合MySQL自身的锁机制

redo日志对应磁盘上MySQL安装目录的ib_logfileN ,

  在这个目录下,没有对应的undo日志,当用户rollback一个事务的时候,缓冲区中所有的数据都被放在了表空间对应的.idb数据文件中。

  

  如图这是某个数据库中的 escore 表 在磁盘上对应的表空间文件,当事务回滚时,会将缓冲区的数据放在 escore.idb 中,并在适当的时候刷新到磁盘。

MySQL事务隔离级别

  SQL标准定义了4种隔离级别,高级别的隔离级别事务安全,并发性能较低,占用资源较多,低级别反之。

  • READ UNCOMMITTED(读未提交内容)
  • READ COMMITTED(读已提交内容)
  • REPEATABLE READ(可重复读)
  • SERIALIZABLE(串行化)

  MySQL查看当前隔离级别和设置隔离级别:

-- 查看隔离级别
mysql> show variables like 'tx_isolation';
--设置隔离级别
mysql> set global transaction isolation level READ UNCOMMITTED;

  READ UNCOMMITTED(读未提交内容)

  在该隔离级别中,所有事务都可以看到其他未提交事务的执行结果,然而其性能也不必其他级别的高很多,因此很少使用,读未提交的数据称为“脏读”。

事务A 事务B

mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set (0.00 sec)

mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select a from test;
+------+
| a |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+------+
5 rows in set (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update test set a=a*2 where a=2;
Query OK, 1 row affected (0.09 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select a from test;
+------+
| a |
+------+
| 1 |
| 4 |
| 3 |
| 4 |
| 5 |
+------+
5 rows in set (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected (0.06 sec)

mysql> select a from test;
+------+
| a |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+------+
5 rows in set (0.00 sec)

 

  READ COMMITTED(读取提交内容)

  一个事务从开始所做的任何改变都是不可见的,事务只能看见已近提交的事务所做的改变,但是一个事务在处理期间可能会发生其他事务修改了数据并提交,那么那么在未提交的事务中就会出现两次读取结果不同的现象,这就是所谓的“不可重复读”。

事务A 事务B

mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set (0.00 sec)

mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select a from test;
+------+
| a |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+------+
5 rows in set (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update test set a=a*2 where a=2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select a from test;
+------+
| a |
+------+
| 1 |
| 4 |
| 3 |
| 4 |
| 5 |
+------+
5 rows in set (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.07 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

 

  REPEATABLE READ(可重复读)

  这是MySQL默认的隔离级别,能确保同一事务的多个实例在并发读取数据时,能看到相同的数据行。但是这种隔离级别也有一个问题:假设一个事务对表中的一行数据进行修改,这种修改会导致整张表的数据都需要更新;同时第二个事务开启,第二个事务是在这张表中插入一行数据。那么,此时就会出现第一个事务发现表中的数据还没有被全部更新的假象,这就是“幻读”。所幸的是在MySQL的InnoDB存储引擎中,通过并发多版本控制的机制已经解决了这个问题。

事务A 事务B

mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)

mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select a from test;
+------+
| a |
+------+
| 1 |
| 4 |
| 3 |
| 4 |
| 5 |
+------+
5 rows in set (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update test set a=0;
Query OK, 5 rows affected (0.00 sec)
Rows matched: 5 Changed: 5 Warnings: 0

mysql> select a from test;
+------+
| a |
+------+
| 1 |
| 4 |
| 3 |
| 4 |
| 5 |
+------+
5 rows in set (0.05 sec)

mysql> commit;
Query OK, 0 rows affected (0.09 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select a from test;
+------+
| a |
+------+
| 0 |
| 0 |
| 0 |
| 0 |
| 0 |
+------+
5 rows in set (0.00 sec)

 

  (InnoDB存储引擎 MVCC机制:InnoDB通过给每个数据行增加两个隐含值的方式来实现。这两个隐含值记录了数据行的创建时间、以及过期时间、每一行存储事件发生时的系统版本号。每次开启一个新的事物版本号就加一,每个事物都会保存开始时的版本号,每次查询根据事物的版本号来查询数据。)

  SERIALIZABLE(串行化)

  这是最高的事务隔离级别,通过强制事务排序,使之不可能产生冲突,从而解决了幻读问题。简单来说就是在每个读取的数据行加上共享锁,这个级别上,可能会导致大量的超时现象和所竞争,一般不使用。

InnoDB锁机制

  在并发系统中,同一时刻可能有多个客户端在对同一张表做更新操作,为了保证数据的一致性,需要对并发加以控制,因此产生了锁。同时为实现事务隔离级别提供保证。

  锁的类型:

  1. 共享锁:代号S,Share的缩写。粒度是行或者N行,一个事务获取共享锁后,可以对锁定范围的数据执行读操作。

  2. 排他锁:代号X,是eXclusive的缩写,粒度同共享锁,一个事务获得排他锁后,可以对锁定范围执行写操作。

  3. 意向锁:是一种表锁,粒度为整张表。分为意向共享锁(IS)和意向排他锁(IX),意向共享锁表示一个事务有意对数据上共享锁或者排它锁,“有意”表示事务想执行操作但是还没有执行。锁与锁之间的关系,要么相容,要么互斥。相容是指:操作同样一组数据时,如果事务A获取了锁a,另一个事务B还可以获取锁b;互斥是指:操作同一组数据时,如果事务A获取了锁a,另一个事务B在事务A释放锁a之前无法获取锁b。

   为了提高数据库的并发控制,每次锁的范围越小越好,越小耗费的资源就越多,系统性能又下降,所以为了找到在并发响应和性能的平衡点,“锁粒度应运而生”。

锁粒度

锁的粒度主要分为表锁和行锁,

表锁管理表的开销最小,同时允许的并发量也是最小的锁机制,MyISAM存储引擎使用该锁机制,当要写入数据时,将整个表锁住,此时读、写动作一律等待,同时一些修改表的记录也是表锁。

行锁可以支持最大的并发,InnoDB存储引擎使用该机制,因为采用行级锁,所以可以获得更多性能。

InnoDB 行级锁演示

事务A 事务B

mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)

mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update test set a= 1 where a=0;
Query OK, 5 rows affected (0.00 sec)
Rows matched: 5 Changed: 5 Warnings: 0

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update test set a= 2 where a=0;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

mysql> commit;
Query OK, 0 rows affected (0.08 sec)

mysql> update test set a= 1 where a=0;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0 Changed: 0 Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

MySQL事务及事务隔离级别 锁机制的更多相关文章

  1. 数据库事务中的隔离级别和锁+spring Transactional注解

    数据库事务中的隔离级别和锁 数据库事务在后端开发中占非常重要的地位,如何确保数据读取的正确性.安全性也是我们需要研究的问题.ACID首先总结一下数据库事务正确执行的四个要素(ACID): 原子性(At ...

  2. Mysql事务,并发问题,锁机制

    .什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点. 原子性:要不全部成功,要不全部撤销 隔离性:事务之间相互独立,互不干扰 一致性:数据库正确地改变状态后,数据库的一致性约束 ...

  3. Mysql事务,并发问题,锁机制-- 幻读、不可重复读(转)

    1.什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点. 原子性:要不全部成功,要不全部撤销 隔离性:事务之间相互独立,互不干扰 一致性:数据库正确地改变状态后,数据库的一致性约 ...

  4. 【转】Mysql事务,并发问题,锁机制

    转自:http://www.cnblogs.com/fidelQuan/p/4549068.html 1.什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点. 原子性:要不全部成 ...

  5. MySQL事务、并发问题、锁机制

    MySQL事务,并发问题,锁机制 1.什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点. 原子性:要不全部成功,要不全部撤销 隔离性:事务之间相互独立,互不干扰 一致性:数据库 ...

  6. [转]数据库事务中的隔离级别和锁+spring Transactional注解

    数据库事务中的隔离级别和锁 数据库事务在后端开发中占非常重要的地位,如何确保数据读取的正确性.安全性也是我们需要研究的问题.ACID首先总结一下数据库事务正确执行的四个要素(ACID): 原子性(At ...

  7. Mysql事务,并发问题,锁机制-- 幻读、不可重复读--专题

    1.什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点. 原子性:要不全部成功,要不全部撤销 隔离性:事务之间相互独立,互不干扰 一致性:数据库正确地改变状态后,数据库的一致性约 ...

  8. 一文彻底读懂MySQL事务的四大隔离级别

    前言 之前分析一个死锁问题,发现自己对数据库隔离级别理解还不够清楚,所以趁着这几天假期,整理一下MySQL事务的四大隔离级别相关知识,希望对大家有帮助~ 事务 什么是事务? 事务,由一个有限的数据库操 ...

  9. mysql事务之间的隔离级别

    事务间未做隔离,会引起下面这些问题. 1.脏读:一个事务可读到另外一个尚未commit的事务中的数据. 2.不可重复读:在一个事务中,读取同一个数据 a,b,按顺序读取,在读a  b 之间,另外一个事 ...

随机推荐

  1. freemodbus modbus TCP 学习笔记

    1.前言     使用modbus有些时间了,期间使用过modbus RTU也使用过modbus TCP,通过博文和大家分享一些MODBUS TCP的东西.在嵌入式中实现TCP就需要借助一个以太网协议 ...

  2. 「小程序JAVA实战」 小程序手写属于自己的第一个demo(六)

    转自:https://idig8.com/2018/08/09/xiaochengxu-chuji-06/ 自己尝试的写一个小demo,用到自定义样式,自定义底部导航,页面之间的跳转等小功能.官方文档 ...

  3. java8新特性-lambda表达式和stream API的简单使用

    一.为什么使用lambda Lambda 是一个 匿名函数,我们可以把 Lambda表达式理解为是 一段可以传递的代码(将代码像数据一样进行传递).可以写出更简洁.更灵活的代码.作为一种更紧凑的代码风 ...

  4. 前端html数组去重的方法

    数组去重 用到的知识点: 1:indexOf() 该方法是返回数组中元素第一次出现的索引值: 如果有,则正常返回索引值: 如果检索的内容不存在于数组中,则返回-1 2:for循环 练习:数组去重 // ...

  5. python调用Go代码

    Go 1.5发布了,其中包含了一个特性:可以编译生成动态链接库,经试验,生成的.so文件可以被python加载并调用.下面举个例子: 先写一个go文件main.go: package main imp ...

  6. java基础面试题 背过1

    web.xml文件中可以配置哪些内容? 答:web.xml用于配置Web应用的相关信息,如:监听器(listener) ContextLoaderListener .过滤器(filter) Strut ...

  7. jq一行一行循环读取table中的元素

    获取当前tr行号,可依据index 获取当前tr对象 获取某一tr下td的内容

  8. sql修改排序规则,区分大小

    alter   database   数据库   COLLATE   Chinese_PRC_CS_AS     修改排序规则,改成大小写敏感的排序规则     如果只修改一个表,用alter   t ...

  9. dynamic和nullable一起使用时的注意

    dynamic和nullable一起使用时的注意

  10. C6678 srio communication via Switch

    First, I don't often give praise for support but I must say Travis, Karthik and Derek from TI have b ...