数据库事务的四个特性
本文介绍了数据库中事务的四个特性(ACID ),并详细介绍了事务的隔离级别。
如果一个数据库声称支持事务处理操作,则该数据库必须具有以下四个特性:
原子性(Atomicity )。
原子是指事务中包含的所有操作都成功,还是全部失败并回滚,这与前面两个博客中介绍事务功能的概念相同。 因此,如果事务处理操作成功,则必须完全应用于数据库;如果操作失败,则必须避免对数据库产生任何影响。
一致性(一致性) )。
一致性意味着事务必须将数据库从一个一致性状态迁移到另一个一致性状态。 这意味着一个事务在执行之前和之后都必须处于一致性状态。
就转账而言,如果用户a和用户b两者的钱加起来都是5000,那么无论a和b之间怎么转账,无论转账多少次,办公结束后两个用户的钱加起来都应该是5000,这就是办公的一致性
隔离性(Isolation ) )。
隔离是指,当多个用户同时访问数据库时,例如,当操作同一表时,数据库打开给每个用户的事务不干扰其他事务的操作,并且多个同时事务之间相互隔离
也就是说,对于任意两个并发事务T1和T2,从事务T1的角度来看,T2可以是在T1开始之前结束的,也可以是在T1结束之后开始的,每个事务都不认为其他事务正在同时执行
事务的隔离数据库提供了几个隔离级别。 稍后说明。
持续性(Durability )
持久性是指提交事务后,对数据库中数据的更改是永久的,即使数据库系统发生故障,提交事务的操作也不会丢失。
例如,如果使用JDBC处理数据库,则在提交事务方法后,将提示用户完成事务操作。 在程序运行完成后,直到出现提示,才能验证事务并正确提交。 此时,即使数据库存在问题,也必须完全执行事务。 否则,将出现严重错误:事务处理已完成,但由于数据库故障而无法执行事务处理。
以上介绍了事务的四个特性(ACID )。 现在,让我们集中讨论事务的隔离性。 当多个线程打开事务处理操作数据库中的数据时,数据库系统必须执行隔离操作,以确保每个线程获取数据的准确性。 首先,在介绍数据库提供的不同隔离级别之前,让我们先看看如果不考虑事务隔离性,则会出现的一些问题。
SQL的四个隔离级别
Read Uncommitted (读取未提交的内容) )。
在此隔离级别上,所有事务都可以看到其他未提交的事务的执行结果。 此隔离级别的性能优于其他级别,因此很少投入使用。 读取未提交的数据也称为脏读。
“Read Committed (读取提交内容)”) )。
这是大多数数据库系统的默认隔离级别。 但是,它不是MySQL的默认值。 它满足了隔离的简单定义。 一个事务只能看到已经提交给办事处的更改。 该隔离级别支持所谓的不可重复读取。 同一事务的其他实例在实例处理期间可能会有新的commit,因此同一选择可能会返回不同的结果。
可重复读取) ) )。
Mysql的默认值为此:REPEATABLE-READ )
这是MySQL的缺省事务隔离级别,使同一事务的多个实例在同时读取数据时显示相同的数据行。 但是,从理论上讲,这引起了另一个棘手的问题。 幻读(Phantom Read )。 简单来说,幻像读取意味着用户读取一个范围内的数据行时,另一个事务会在该范围内插入新行,而用户读取该范围内的数据行时,会有新的“幻影”行。 InnoDB和Falcon存储引擎通过MVCC、multiversionconcurrencycontrol机制解决了此问题。
可序列化)。
这是最高的隔离级别,通过强制事务排序以避免冲突来解决幻像读取问题。 简单来说,就是对要读取的数据的各行施加共享锁定。 在这个水平上,可能会引起大量的超时现象和锁定竞争。
读取相同数据时,容易出现的问题如下。
脏读:如果一个事务更新一个数据,另一个事务当前读取相同的数据,并且由于任何原因操作了上一个回滚,则下一个事务读取的数据不正确。
“不可重读”(Non-repeatable read ) :在事务的两次查询中数据不匹配。 这可能是在两次查询过程之间插入了事务更新的原始数据。
幻读:在一个事务的两次查询中数据数量不匹配。 例如,假设一个事务查询某列)中的数据,而另一个事务在该点插入新列中的数据。 上一个事务在以下查询中查找以前没有的列中的数据:
隔离级别
潦草的读法
不可再现度
幻读
Read Uncommitted (读取未提交的内容) )。
“Read Committed (读取提交内容)”) )。
r
epeatable Read(可重读)×
×
√
Serializable(可串行化)
×
×
×
设置MySQL的事务隔离级别
windows:
查询显示当前的隔离级别
mysql> show global variables like '%isolation%';
+-----------------------+-----------------+
| Variable_name | Value |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.00 sec)
设置隔离级别
mysql> set global transaction_isolation ='read-committed';
Query OK, 0 rows affected (0.00 sec)
mysql> show global variables like '%isolation%';
+-----------------------+----------------+
| Variable_name | Value |
+-----------------------+----------------+
| transaction_isolation | READ-COMMITTED |
+-----------------------+----------------+
1 row in set (0.00 sec)
查看隔离级别也可以(前提是知道具体变量名):
mysql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ |
+-------------------------+
1 row in set (0.00 sec)
Linux
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
在位置:
lc-messages-dir = /usr/share/mysql
skip-external-locking
后面添加(读取提交内容):
transaction-isolation = READ-COMMITTED
保存后重启mysql服务:
sudo service mysql restart