数据库事务与锁

事务隔离级别

  1. 脏读
    事务中可以读到未提交事务修改的数据。
  2. 不可重复读
    事务中先后读取同一条记录,值不相同的现象。例如:A事务中读取一条数据,其值为1,B事务修改了其值为2,B事务提交后,A事务再次读取这条数据,其值变成了2。
  3. 幻读
    事务中先后以某条件读取一张表,记录数不同的现象。
事务隔离级别 脏读 不可重复读 幻读
read uncommitted
read committed ×
repeatable read × ×
serialized × × ×
1.读已提交(read committed) ??PG中默认的隔离级别。 当一个事务运行使用这个隔离级别时, 一个查询(没有FOR UPDATE/SHARE子句)只能看到查询开始之前已经被提交的数据, 而无法看到未提交的数据或在查询执行期间其它事务提交的数据。
??实际上,SELECT查询看到的是一个在查询开始运行的瞬间该数据库的一个快照。不过SELECT可以看见在它自身事务中之前执行的更新的效果,即使它们还没有被提交。
2.可重复读(repeatable read) ??可重复读隔离级别只看到在事务开始之前被提交的数据,不过,查询能够看见在它的事务中之前执行的更新,即使它们还没有被提交。
??这个级别与读已提交不同之处在于,一个可重复读事务中的查询看到 事务中第一个非事务控制语句开始时的一个快照, 而不是事务中当前语句开始时的快照。
??当处于可重复读事务中时,如果要修改的记录,与事务开始时的数据快照不一致时,修改该记录会发生ERROR: could not serialize access due to concurrent update异常,导致回滚。
3.可序列化(serializable) 【数据库事务与锁】??待补充
试验(基于Postgresql) 试验1 事务A隔离级别:read committed
事务B隔离级别:read committed
A: begin transaction isolation level read committed; update usr set name = 'admin' where id = 1; //update语句在这条记录上增加了共享锁,其他事务可读不可写B: begin transaction isolation level read committed; select * from usr where id = 1; //可以读 +----+-----------+ | id | name| +----+-----------+ |1 | admin1111 | +----+-----------+ update usr set name = 'admin1111' where id = 1; //不可修改,发生了阻塞,等待上一事务结束A: commit; B: //阻塞停止,update生效 commit; select * from usr where id = 1; +----+-----------+ | id | name| +----+-----------+ |1 | admin1111 | +----+-----------+

试验2 事务A隔离级别:repeatable read
事务B隔离级别:repeatable read
2.1 事务提交
A: begin transaction isolation level repeatable read; update usr set name = 'AAA' where id = 1; //加共享锁B: begin transaction isolation level repeatable read; select * from usr where id =1; +----+-----------+ | id | name| +----+-----------+ |1 | admin1111 | +----+-----------+ update usr set name = 'BBB' where id = 1; //不可修改,发生了阻塞,等待上一事务结束A: commit; B: ///阻塞停止,更新失败 ERROR:could not serialize access due to concurrent updateselect * from usr where id =1; +----+------+ | id | name | +----+------+ |1 | AAA| +----+------+

2.2事务回滚
A: begin transaction isolation level repeatable read; update usr set name = 'AAA' where id = 1; //加共享锁 B: begin transaction isolation level repeatable read; select * from usr where id =1; +----+-----------+ | id | name| +----+-----------+ |1 | admin1111 | +----+-----------+ update usr set name = 'BBB' where id = 1; //不可修改,发生了阻塞,等待上一事务结束A: rollback; B: ///阻塞停止,update生效 select * from usr where id =1; +----+------+ | id | name | +----+------+ |1 | B| +----+------+

参考资料:http://www.postgres.cn/docs/9.5/transaction-iso.html

    推荐阅读