1.事务具有ACID四种特性。
1.原子性(automicity):一个事务中的所有语句,应该做到:要么全做,要么一个都不做;
2.一致性(consisitency):让数据保持逻辑上的“合理性”,比如:一个商品出库时,既要让商品库中的该商品数量减1,又要让对应用户的购物车中的该商品加1;
3.隔离性(isolation):如果多个事务同时并发执行,但每个事务就像各自独立执行一样。
4.持久性(durability):一个事务执行成功,则对数据来说应该是一个明确的硬盘数据更改(而不仅仅是内存中的变化)
2. 事务的隔离级别及产生的相关问题
脏读 (dirty read)事务T1更新了一行记录的内容,但是并没有提交所做的修改。事务T2读取更新后的行,然后T1执行回滚操作,取消了刚才所做的修改。现在T2所读取的行就无效了。
不可重复读取 (nonrepeatable read)事务T1读取一行记录,紧接着事务T2修改 了T1刚才读取的那一行记录。然后T1又再次读取这行记录,发现与刚才读取的结果不同。这就称为“不可重复”读,因为T1原来读取的那行记录已经发生了变化。
幻读 (phantom read)事务T1读取一条指定的WHERE子句所返回的结果集。然后事务T2新插入 一行记录,这行记录恰好可以满足T1所使用的查询条件中的WHERE 子句的条件。然后T1又使用相同的查询再次对表进行检索,但是此时却看到了事务T2刚才插入的新行。这个新行就称为“幻像”,因为对T1来说这一行就像突 然出现的一样。
3.MySQL的InnoDB引擎中事物与锁
锁机制
1) 共享锁:由读表操作加上的锁,加锁后其他用户只能获取该表或行的共享锁,不能获取排它锁,也就是说只能读不能写。
2) 排它锁:由写表操作加上的锁,加锁后其他用户不能获取该表或行的任何锁,典型是mysql事务中的DML语句INSERT,DELETE,UPDATE.
锁的范围:
行锁: 对某行记录加上锁
表锁: 对整个表加上锁
这样组合起来就有,行级共享锁,表级共享锁,行级排他锁,表级排他锁。
3.1 SELECT …… LOCK IN SHARE MODE
在读取的行上设置一个共享模式的锁。这个共享锁允许其它会话(session)读取数据但不允许修改它。 行读取的是最新的数据,如果他被其它事务使用中而没有提交,读取锁将被阻塞知道那个事务结束。
3.2 SELECT ….. FOR UPDATE
在读取行上设置一个排他锁。组织其他session读取或者写入行数据
3.3 INSERT、UPDATE、DELETE
会话事务会对DML语句操作的数据加上一个独占锁,其他会话的事务都将会等待其释放独占锁。
3.4 gap and next key lock(间隙锁)
InnoDB引擎会自动给会话事务中的共享锁、更新琐以及独占锁,需要加到一个区间值域的时候,再加上个间隙锁(或称范围锁),对不存在的数据也锁住,防止出现幻读。
3.5表锁
LOCK TABLES tablename WRITE;
LOCK TABLES tablename READ;
UPDATE ....;
UNLOCK TABLES;
4.mysql中innodb引擎演示REPEATABLE-READ
创建一个innodb引擎的表
CREATE TABLE t_innodb(
`ID` int NOT NULL AUTO_INCREMENT,
`NUM` int,
PRIMARY KEY (`ID`)
)ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE utf8_general_ci;
#表中插入一条记录
INSERT INTO t_innodb (`ID`, `NUM`) VALUES (NULL, 1);
查看和设置设置隔离级别:
#查看InnoDB系统级别的事务隔离级别
SELECT @@global.tx_isolation;
#查看InnoDB会话级别的事务隔离级别
SELECT @@tx_isolation;
#设置InnoDB系统级别的事务隔离级别
set @@global.tx_isolation = 'REPEATABLE-READ';
#设置InnoDB会话级别的事务隔离级别
set tx_isolation='REPEATABLE-READ';
在session 1中开启事务,并且修改字段num的值:
START TRANSACTION;
UPDATE t_innodb SET num = num+ 1 WHERE id = 1;
#修改num的值后,查询到num变成了2
SELECT * from t_innodb WHERE id = 1;
在命令行窗口开启session 2
在session 1中commit事务
在session 2中
下面验证下EPEATABLE-READ会不会出现幻读
在session 1中再插入数据:
在 session 2中
可见:Mysql InnoDB的可重复读隔离级别和其他数据库的可重复读是有区别的,不会造成幻象读(phantom read)。
引用:
[1] MySQL中的行级锁SELECT FOR UPDATE 和LOCK IN SHARE MODE 区别
[2]mysql事务隔离级别以及有问题的读取(脏读,不可重复读,幻象读)
[3]MYSQL数据库事务处理和锁机制