什么是事务?

当多个用户访问同一份数据时,一个用户在更改数据的过程中可能有其他用户同时发起更改请求,为保证数据库记录的更新从一个一致性状态更改为另一个一致性状态,这样的操作过程就是事务。事务具有的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. clock函数返回负值~ (转)

    使用clock() 函数来进行计时,时不时的返回一个很大的负数,怎么检查也检查不出错误,现在找出错误原因,给大家分享一下. 来源网页:http://kebe-jea.blogbus.com/logs/ ...

  2. python 中 print 函数用法总结

    Python 思想: “一切都是对象!” 在 Python 3 中接触的第一个很大的差异就是缩进是作为语法的一部分,这和C++等其他语言确实很不一样,所以要小心 ,其中python3和python2中 ...

  3. Tornado之抽屉实战(3)--注册

    知识点应用:标签绑定事件,jQuery获取用户值-->AJAX发送数据-->后台路由系统-->业务逻辑处理-->ORM数据操作-->write返回-->AJAX回调 ...

  4. 并发之AbstractQueuedLongSynchronize----AQS

    一概述 谈论到并发,不得不谈论锁,而谈论到锁而言,又离不开ReentrantLock.ReentrantLock是锁锁的一种实现方式,对于锁而言,我们这里就需要讨论到AQS,即上面的AbstractQ ...

  5. 4-3 线程安全性-原子性-synchronized

    原子性它提供了互斥访问,同一时刻只能有一个线程来对它进行操作.能保证同一时刻只有一个线程来对其进行操作的,除了Atomic包之外,还有锁.JDK提供锁主要分两种,synchronized是一个Java ...

  6. elasticsearch2.x插件之一:kopf

    kopf kopf is a simple web administration tool for elasticsearch written in JavaScript + AngularJS + ...

  7. 高性能的城市定位API接口

    如果不需要精准的定位,还有一种通过IP地址获取当前城市的方法,采用新浪的api接口. <script src="http://int.dpool.sina.com.cn/iplooku ...

  8. SSL认证

    SSL认证 单向认证 1.发一串消息个对方 2.对方用私钥加密后返回 3.本方用对方的公钥解密,验证消息是否正确, 如果消息相同,则本方认可对方 双向认证 本方认证对方 对方认证本方

  9. 基于 EntityFramework 的数据库主从读写分离架构 - 目录

    基于 EntityFramework 的数据库主从读写分离架构       回到目录,完整代码请查看(https://github.com/cjw0511/NDF.Infrastructure)中的目 ...

  10. c语言实战 BJT时间转化位UTC时间

    题目是这样的: 题目内容: UTC是世界协调时,BJT是北京时间,UTC时间相当于BJT减去8.现在,你的程序要读入一个整数,表示BJT的时和分.整数的个位和十位表示分,百位和千位表示小时.如果小时小 ...