事务(Transaction)是数据库系统中一系列操作的一个逻辑单元,所有操作要么全部成功要么全部失
败。 事务是区分文件存储系统与Nosql数据库重要特性之一,其存在的意义是为了保证即使在并发情况下也
能正确的执行CRUD操作。怎样才算是正确的呢?这时提出了事务需要保证的四个特性即ACID:
在高并发的情况下,要完全保证其ACID特性是非常困难的,除非把所有的事务串行化执行,但带来的负 面的影响将是性能大打折扣。很多时候我们有些业务对事务的要求是不一样的,所以数据库中设计了四 种隔离级别,供用户基于业务进行选择。这四种隔离级别分别是:
其中,Oracle默认的级别是read committed,而MySQL默认为repeatable read。
注:MySQL中查看、设置事务隔离级别:
#查看事务隔离级别
SELECT @@tx_isolation;
#设置隔离级别为read-uncommitted
set tx_isolation='read-uncommitted';
采用不同的事务隔离级别,可解决不同的问题,总结如下:
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
read uncommitted | 不可解决 | 不可解决 | 不可解决 |
read committed | 可解决 | 不可解决 | 不可解决 |
repeatable read | 可解决 | 可解决 | 不可解决 |
serializable | 可解决 | 可解决 | 可解决 |
可以看到,隔离级别越高,事务的安全性就越高,但是对性能的影响也越大,实际应用中应根据不同业务场景选择不同的隔离级别。
CREATE TABLE `account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL,
`money` bigint(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
#设置为读未提交
set tx_isolation='read-uncommitted';
BEGIN;
insert INTO `account` (`name`,`money`) VALUES ('Kobe',100);
#设置为读未提交
set tx_isolation='read-uncommitted';
SELECT * from `account`;
insert INTO `account` (`name`,`money`) VALUES ('Kobe',100);
#设置为读已提交
set tx_isolation='read-committed';
BEGIN;
SELECT * from `account`;
# 其他操作
此时查询到表中的数据是{1,Kobe,100}。
这时session2更新了表中的数据
#设置为读已提交
set tx_isolation='read-committed';
UPDATE `account` SET money= money+100 where `id`=1;
SELECT * from `account`;
insert INTO `account` (`name`,`money`) VALUES ('Kobe',);
#设置为可重复读
set tx_isolation='REPEATABLE-READ';
BEGIN;
SELECT * FROM `account`;
#设置为可重复读
set tx_isolation='REPEATABLE-READ';
insert INTO `account` (`name`,`money`) VALUES ('James',100);