首页
随机
最近更改
特殊页面
社群首页
参数设置
关于WHY42
免责声明
WHY42
搜索
用户菜单
登录
欢迎来到Riguz的小站!这是一个私人wiki,用来记录一些我的笔记。
查看“︁MySQL:Transaction”︁的源代码
←
MySQL:Transaction
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
=ACID= ACID,指数据库事务正确执行的四个基本要素的缩写。包含: * 原子性(Atomicity) * 一致性(Consistency) * 隔离性(Isolation) * 持久性(Durability) 一个支持事务(Transaction)的数据库,必需要具有这四种特性,否则在事务过程(Transaction processing)当中无法保证数据的正确性,交易过程极可能达不到交易方的要求。 ==原子性== 整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。 ==一致性== *强一致性:读操作可以立即读到提交的更新操作。 *弱一致性:提交的更新操作,不一定立即会被读操作读到,此种情况会存在一个不一致窗口,指的是读操作可以读到最新值的一段时间。 *最终一致性:是弱一致性的特例。事务更新一份数据,最终一致性保证在没有其他事务更新同样的值的话,最终所有的事务都会读到之前事务更新的最新值。如果没有错误发生,不一致窗口的大小依赖于:通信延迟,系统负载等。 其他一致性变体还有: *单调一致性:如果一个进程已经读到一个值,那么后续不会读到更早的值。 *会话一致性:保证客户端和服务器交互的会话过程中,读操作可以读到更新操作后的最新值。 ==隔离性== ===脏读Dirty reads=== <q> A dirty read (aka uncommitted dependency) occurs when a transaction is allowed to read data from a row that has been modified by another running transaction and not yet committed. </q> 事务A修改了一个数据,但未提交,事务B读到了事务A未提交的更新结果,如果事务A提交失败,事务B读到的就是脏数据。 {| class="two-columns" |- ! Transaction 1 !! Transaction 2 |- | <syntaxhighlight lang="sql"> /* Query 1 */ SELECT age FROM users WHERE id = 1; /* will read 20 */ </syntaxhighlight> || - |- | - || <syntaxhighlight lang="sql"> /* Query 2 */ UPDATE users SET age = 21 WHERE id = 1; /* No commit here */ </syntaxhighlight> |- | <syntaxhighlight lang="sql"> /* Query 1 */ SELECT age FROM users WHERE id = 1; /* will read 21 */ </syntaxhighlight> || - |- | - || <syntaxhighlight lang="sql"> ROLLBACK; /* lock-based DIRTY READ */ </syntaxhighlight> |} ===不可重复读 Non-repeatable reads=== 在同一个事务中,对于同一份数据读取到的结果不一致。比如,事务B在事务A提交前读到的结果,和提交后读到的结果可能不同。不可重复读出现的原因就是事务并发修改记录,要避免这种情况,最简单的方法就是对要修改的记录加锁,这回导致锁竞争加剧,影响性能。另一种方法是通过MVCC可以在无锁的情况下,避免不可重复读。 {| class="two-columns" |- ! Transaction 1 !! Transaction 2 |- | <syntaxhighlight lang="sql"> /* Query 1 */ SELECT * FROM users WHERE id = 1; </syntaxhighlight> || - |- | - || <syntaxhighlight lang="sql"> /* Query 2 */ UPDATE users SET age = 21 WHERE id = 1; COMMIT; /* in multiversion concurrency control, or lock-based READ COMMITTED */ </syntaxhighlight> |- | <syntaxhighlight lang="sql"> /* Query 1 */ SELECT * FROM users WHERE id = 1; COMMIT; /* lock-based REPEATABLE READ */ </syntaxhighlight> || - |} ===幻读Phantom reads=== 在同一个事务中,同一个查询多次返回的结果不一致。事务A新增了一条记录,事务B在事务A提交前后各执行了一次查询操作,发现后一次比前一次多了一条记录。幻读是由于并发事务增加记录导致的,这个不能像不可重复读通过记录加锁解决,因为对于新增的记录根本无法加锁。需要将事务串行化,才能避免幻读。 {| class="two-columns" |- ! Transaction 1 !! Transaction 2 |- | <syntaxhighlight lang="sql"> /* Query 1 */ SELECT * FROM users WHERE age BETWEEN 10 AND 30; </syntaxhighlight> || - |- | - || <syntaxhighlight lang="sql"> /* Query 2 */ INSERT INTO users(id, name, age) VALUES (3, 'Bob', 27); COMMIT; </syntaxhighlight> |- | <syntaxhighlight lang="sql"> /* Query 1 */ SELECT * FROM users WHERE age BETWEEN 10 AND 30; COMMIT; </syntaxhighlight> || - |} ===隔离级别(SQL:1992)=== 事务的隔离级别从低到高有: ;Read Uncommitted:最低的隔离级别,什么都不需要做,一个事务可以读到另一个事务未提交的结果。所有的并发事务问题都会发生。 ;Read Committed:只有在事务提交后,其更新结果才会被其他事务看见。可以解决脏读问题。 ;Repeatable reads:在一个事务中,对于同一份数据的读取结果总是相同的,无论是否有其他事务对这份数据进行操作,以及这个事务是否提交。可以解决脏读、不可重复读。 ;Serializable:事务串行化执行,隔离级别最高,牺牲了系统的并发性。可以解决并发事务的所有问题。 ==持久性== 事务提交后,对系统的影响是永久的。 =MySQL= MySQL支持SQL92标准中定义的各种事务隔离级别。InnoDB引擎默认支持的级别是<syntaxhighlight lang="lua" inline>REPEATABLE READ</syntaxhighlight> * 在REPEATABLE READ级别下,InnoDB通过<syntaxhighlight lang="lua" inline>next-key locks</syntaxhighlight>防止幻读。 See: * https://dev.mysql.com/doc/refman/8.0/en/innodb-introduction.html [[Category:MySQL]] [[Category:Database]]
返回
MySQL:Transaction
。