搜索
首页数据库mysql教程mysql中acid是什么

本篇文章给大家介绍一下mysql中的acid。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。

mysql中acid是什么

一、事务的基本要素(ACID)

  1、原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。

   2、一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。其实一致性也是因为原子型的一种表现

   3、隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。串行化

   4、持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。

二、事务的并发问题

  1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据,与表中最终的实际数据不一致

  2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。读取结果与上次结果不一致

  3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。修改过来了但又被改了,导致结果和预期不一样

  小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

三、MySQL事务隔离级别

事务隔离级别 脏读 不可重复读 幻读
读未提交(read-uncommitted)
读已提交(read-committed)
可重复读(repeatable-read)
串行化(serializable)

mysql默认的事务隔离级别为repeatable-read

四、用例子说明各个隔离级别的情况

  1、读未提交:

    (1)打开一个客户端A,并设置当前事务模式为read uncommitted(未提交读),查询表account的初始值:

    (2)在客户端A的事务提交之前,打开另一个客户端B,更新表account:

    (3)这时,虽然客户端B的事务还没提交,但是客户端A就可以查询到B已经更新的数据:

 

    (4)一旦客户端B的事务因为某种原因回滚,所有的操作都将会被撤销,那客户端A查询到的数据其实就是脏数据:

     (5)在客户端A执行更新语句update account set balance = balance - 50 where id =1,lilei的balance没有变成350,居然是400,是不是很奇怪,数据不一致啊,如果你这么想就太天真 了,在应用程序中,我们会用400-50=350,并不知道其他会话回滚了,要想解决这个问题可以采用读已提交的隔离级别

   2、读已提交

    (1)打开一个客户端A,并设置当前事务模式为read committed(未提交读),查询表account的初始值:

    (2)在客户端A的事务提交之前,打开另一个客户端B,更新表account:

    (3)这时,客户端B的事务还没提交,客户端A不能查询到B已经更新的数据,解决了脏读问题:

    (4)客户端B的事务提交

    (5)客户端A执行与上一步相同的查询,结果 与上一步不一致,即产生了不可重复读的问题

   3、可重复读

     (1)打开一个客户端A,并设置当前事务模式为repeatable read,查询表account

    (2)在客户端A的事务提交之前,打开另一个客户端B,更新表account并提交

    (3)在客户端A执行步骤(1)的查询:

    (4)执行步骤(1),lilei的balance仍然是400与步骤(1)查询结果一致,没有出现不可重复读的 问题;接着执行update balance = balance - 50 where id = 1,balance没有变成400-50=350,lilei的balance值用的是步骤(2)中的350来算的,所以是300,数据的一致性倒是没有被破坏,这个有点神奇,也许是mysql的特色吧,做dml时可重复读数据还是按表中真实数据来

mysql> select * from account;
+------+--------+---------+
| id   | name   | balance |
+------+--------+---------+
|    1 | lilei  |     400 |
|    2 | hanmei |   16000 |
|    3 | lucy   |    2400 |
+------+--------+---------+
3 rows in set (0.00 sec)

mysql> update account set balance = balance - 50 where id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from account;
+------+--------+---------+
| id   | name   | balance |
+------+--------+---------+
|    1 | lilei  |     300 |
|    2 | hanmei |   16000 |
|    3 | lucy   |    2400 |
+------+--------+---------+
3 rows in set (0.00 sec)

    (5) 在客户端A提交事务,查询表account的初始值

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

mysql> select * from account;
+------+--------+---------+
| id | name | balance |
+------+--------+---------+
| 1 | lilei | 300 |
| 2 | hanmei | 16000 |
| 3 | lucy | 2400 |
+------+--------+---------+
3 rows in set (0.00 sec)

    (6)在客户端B开启事务,新增一条数据,其中balance字段值为600,并提交

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

mysql> insert into account values(4,'lily',600);
Query OK, 1 row affected (0.00 sec)

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

    (7) 在客户端A计算balance之和,值为300+16000+2400=18700,没有把客户端B的值算进去,客户端A提交后再计算balance之和,居然变成了19300,这是因为把客户端B的600算进去了

,站在客户的角度,客户是看不到客户端B的,它会觉得是天下掉馅饼了,多了600块,这就是幻读,站在开发者的角度,数据的 一致性并没有破坏。但是在应用程序中,我们得代码可能会把18700提交给用户了,如果你一定要避免这情况小概率状况的发生,那么就要采取下面要介绍的事务隔离级别“串行化” 

mysql> select sum(balance) from account;
+--------------+ 
| sum(balance) | 
+--------------+ 
| 18700 |
+--------------+
1 row in set (0.00 sec)
mysql> commit;
 Query OK, 0 rows affected (0.00 sec)
mysql> select sum(balance) from account;
 +--------------+ 
 | sum(balance) | 
 +--------------+
 | 19300 |
 +--------------+ 
 1 row in set (0.00 sec)

  4.串行化

    (1)打开一个客户端A,并设置当前事务模式为serializable,查询表account的初始值:

mysql> set session transaction isolation level serializable;
Query OK, 0 rows affected (0.00 sec)

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

mysql> select * from account;
+------+--------+---------+
| id   | name   | balance |
+------+--------+---------+
|    1 | lilei  |   10000 |
|    2 | hanmei |   10000 |
|    3 | lucy   |   10000 |
|    4 | lily   |   10000 |
+------+--------+---------+
4 rows in set (0.00 sec)

    (2)打开一个客户端B,并设置当前事务模式为serializable,插入一条记录报错,表被锁了插入失败,mysql中事务隔离级别为serializable时会锁表,因此不会出现幻读的情况,这种隔离级别并发性极低,开发中很少会用到。

mysql> set session transaction isolation level serializable;
Query OK, 0 rows affected (0.00 sec)
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into account values(5,'tom',0);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

补充:

  1、SQL规范所规定的标准,不同的数据库具体的实现可能会有些差异

  2、mysql中默认事务隔离级别是可重复读时并不会锁住读取到的行

  3、事务隔离级别为读提交时,写数据只会锁住相应的行

  4、事务隔离级别为可重复读时,如果有索引(包括主键索引)的时候,以索引列为条件更新数据,会存在间隙锁间隙锁、行锁、下一键锁的问题,从而锁住一些行;如果没有索引,更新数据时会锁住整张表。

  5、事务隔离级别为串行化时,读写数据都会锁住整张表

   6、隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大,鱼和熊掌不可兼得啊。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed,它能够避免脏读取,而且具有较好的并发性能。尽管它会导致不可重复读、幻读这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。

相关推荐:《mysql教程

以上是mysql中acid是什么的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:CSDN。如有侵权,请联系admin@php.cn删除
如何使用Alter Table语句在MySQL中更改表?如何使用Alter Table语句在MySQL中更改表?Mar 19, 2025 pm 03:51 PM

本文讨论了使用MySQL的Alter Table语句修改表,包括添加/删除列,重命名表/列以及更改列数据类型。

如何为MySQL连接配置SSL/TLS加密?如何为MySQL连接配置SSL/TLS加密?Mar 18, 2025 pm 12:01 PM

文章讨论了为MySQL配置SSL/TLS加密,包括证书生成和验证。主要问题是使用自签名证书的安全含义。[角色计数:159]

您如何处理MySQL中的大型数据集?您如何处理MySQL中的大型数据集?Mar 21, 2025 pm 12:15 PM

文章讨论了处理MySQL中大型数据集的策略,包括分区,碎片,索引和查询优化。

哪些流行的MySQL GUI工具(例如MySQL Workbench,PhpMyAdmin)是什么?哪些流行的MySQL GUI工具(例如MySQL Workbench,PhpMyAdmin)是什么?Mar 21, 2025 pm 06:28 PM

文章讨论了流行的MySQL GUI工具,例如MySQL Workbench和PhpMyAdmin,比较了它们对初学者和高级用户的功能和适合性。[159个字符]

如何使用Drop Table语句将表放入MySQL中?如何使用Drop Table语句将表放入MySQL中?Mar 19, 2025 pm 03:52 PM

本文讨论了使用Drop Table语句在MySQL中放下表,并强调了预防措施和风险。它强调,没有备份,该动作是不可逆转的,详细介绍了恢复方法和潜在的生产环境危害。

您如何用外国钥匙代表关系?您如何用外国钥匙代表关系?Mar 19, 2025 pm 03:48 PM

文章讨论了使用外国密钥来代表数据库中的关系,重点是最佳实践,数据完整性和避免的常见陷阱。

如何在JSON列上创建索引?如何在JSON列上创建索引?Mar 21, 2025 pm 12:13 PM

本文讨论了在PostgreSQL,MySQL和MongoDB等各个数据库中的JSON列上创建索引,以增强查询性能。它解释了索引特定的JSON路径的语法和好处,并列出了支持的数据库系统。

如何保护MySQL免受常见漏洞(SQL注入,蛮力攻击)?如何保护MySQL免受常见漏洞(SQL注入,蛮力攻击)?Mar 18, 2025 pm 12:00 PM

文章讨论了使用准备好的语句,输入验证和强密码策略确保针对SQL注入和蛮力攻击的MySQL。(159个字符)

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器