postgresql系列_MVCC机制以及锁机制理解

数据库操作遇到的问题

  1. 脏读:一个事务读取了另一个未提交事务写入的数据;
  2. 不可重复读:一个事务重新读取前面读取过的数据,发现该数据已经被另一个已经提交的事务修改;
  3. 幻读:一个事务重新执行一个查询,返回符合查询条件的行的集合,发现满足查询条件的行的集合因为其它最近提交的事务而发生了改变。

事务特性

  1. 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行;
  2. 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束;
  3. 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行;
  4. 持久性(Durability):一个事务一旦提交,他对数据库的修改应该永久保存在数据库中。

数据库事务隔离级别

  1. 读未提交(READ UNCOMMITTED)
  2. 读已提交(READ COMMITTED)
  3. 可重复读(REPEATABLE READS)
  4. 可序列化(SERIALIZABLE)

数据库事务隔离级别&&解决问题

数据库事务隔离级别.png

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

乐观锁与悲观锁

参考:http://www.hollischuang.com/archives/934

MVCC(multiversion concurrency control,多版本并发控制)

  1. MVCC(多版本并发控制)与使用锁的优缺点:
    在MVCC里,对检索(读)数据的锁请求与写数据的锁请求不冲突,所以读不会阻塞写,而写也从不阻塞读。甚至当通过创新的序列化快照隔离(SSI)级别提供事务隔离的严格等级时,PostgreSQL维持这样的保证。
    在PostgreSQL里也有表和行级别的锁定机制,用于给那些无法轻松接受MVCC行为的应用。 不过,恰当地使用MVCC总会提供比锁更好的性能。另外,由应用定义的咨询锁提供了一个获得不依赖于单独事务的锁的机制。
    问题:PG什么时候选择MVCC什么时候选择使用锁?
    在PostgreSQL里也有表和行级别的锁功能,用于那些通常不需要完整事务隔离并且想要显式管理特定冲突点的应用。不过,恰当地使用MVCC通常会提供比锁更好的性能。

  2. MVCC的两种实现方法

  3. 写新数据时,把旧数据移到一个单独的地方,如回滚段中,其他人读数据时,从回滚段中把旧的数据读出来;
    2.写数据时,旧数据不删除,而是把新数据插入。PostgreSQL数据库使用第二种方法,而Oracle数据库和MySQL中的innodb引擎使用的是第一种方法;

  4. 与oracle数据库和MySQL中的innodb引擎相比较,PostgreSQL的MVCC实现方式的优缺点如下:

    • 优点:
      1. 事务回滚可以立即完成,无论事务进行了多少操作;
      2. 数据可以进行很多更新,不必像Oracle和MySQL的Innodb引擎那样需要经常保证回滚段不会被用完,也不会像oracle数据库那样经常遇到“ORA-1555”错误的困扰;
    • 缺点:
      1. 旧版本数据需要清理。PostgreSQL清理旧版本的命令成为Vacuum;
      2. 旧版本的数据会导致查询更慢一些,因为旧版本的数据存在于数据文件中,查询时需要扫描更多的数据块。

PG中delete和update语句机制

在PostgreSQL中,使用delete和update语句删除或更新的数据行并没有被实际删除,而只是在旧版本数据行的物理地址上将该行的状态置为已删除或已过期。因此当数据表中的数据变化极为频繁时,那么在一段时间之后该表所占用的空间将会变得很大,然而数据量却可能变化不大。要解决该问题,需要定期对数据变化频繁的数据表执行VACUUM操作

  • 无VACUUM:只是将删除的数据状态置为已删除,该空间不能记录被重新使用.
  • VACUUM:删除的记录位于末端,占用的空间会被物理释放归还操作系统,如果不是位于末端,会将删除数据锁占用的空间置为可用状态.
  • VACUUM FULL:不论被删除的数据是否处于数据表末端,这些数据锁占用的空间都将被物理释放并归还操作系统.
    下面的blog详细分析了vacuum和vacuum full的区别,以及如何恢复索引和delete后的磁盘空间:
    http://www.cnblogs.com/stephen-liu74/archive/2011/12/27/2304155.html

PG的MVCC实现机制(以insert形式展开说明)

在Postgres中,每一个事务都会得到一个被称作为 XID 的事务ID。这里说的事务不仅仅是被 BEGIN - COMMIT 包裹的一组语句,还包括单条的insert、update或者delete语句。当一个事务开始时,Postgrel递增XID,然后把它赋给这个事务。Postgres还在系统里的每一行记录上都存储了事务相关的信息,这被用来判断某一行记录对于当前事务是否可见。
insert的MVCC说明:

  1. 当插入一行记录时,PG会把当前事务的XID存储在这行数据中的xmin;
  2. 当插入的数据未COMMIT之前,这行数据对其他数据是不可见的;
  3. 当插入的数据COMMIT后,这行数据对其他数据是可见的;
  4. 资料说只有xmin<XID条件,才能查看这条新记录,但测试发现可能存在可重复读;
  • 事务1:
    事务ID:x
    查询数据1;
    阻塞;
    查询数据2;
  • 事务2:
    事务ID:x+1
    插入数据

上面2个示例,如果事务2在事务1阻塞的时候提交,在事务1中的查询数据2是能查看到这条新数据的,因为PG默认的事务隔离级别是读已提交.如果更改事务隔离级别为SERIALIZABLE后,则不会发生可重复读的情况(即查询1和查询2两次的结果一致).
自己测试查看语句:

--获取行xmin,xmax值
select xmin, xmax,* from tablename;
--获取当前事务的XID
select txid_current();
--改变事务隔离级别
BEGIN TRANSACTION ISOLATION LEVEl [READ COMMITTED/REPEATABLE READ/SERIALIZABLE];  --一次启动事务并指定事务隔离级别

对于delete和update来说,机制也是类似的,当对于他们来说PG使用xmax来判断数据的可见性.
自己测试思路可以参考:
http://www.zlovezl.cn/articles/postgresql-concurrency-with-mvcc/
原理也可参考:
说明:https://my.oschina.net/Kenyon/blog/108850
示例:https://my.oschina.net/Kenyon/blog/63668

PG中的事务隔离

PG的表锁

PG文档表锁机制:http://www.postgres.cn/docs/9.5/explicit-locking.html#LOCKING-TABLES
通过实例较好的说明了PG的锁机制:http://www.oschina.net/translate/postgresql-locking-revealed

PG的行锁

PG文档行级锁:http://www.postgres.cn/docs/9.5/explicit-locking.html#LOCKING-ROWS
pg行锁解读:http://blog.itpub.net/30088583/viewspace-1699315/

PG事务常用操作

  • 开启事务
BEGIN;
START TRANSACTION [ transaction_mode [, ...] ]
-这里的 transaction_mode是下列之一:
-    ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }
-    READ WRITE | READ ONLY
-    [ NOT ] DEFERRABLE
  • 设置事务模式
SET TRANSACTION transaction_mode [, ...]
SET TRANSACTION SNAPSHOT snapshot_idSET SESSION CHARACTERISTICS AS TRANSACTION transaction_mode [, ...] 
-这里的 transaction_mode是下列之一:
-    ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }
-    READ WRITE | READ ONLY
-    [ NOT ] DEFERRABLE
--事务隔离级别,定义多个事务时间的隔离级别
BEGIN TRANSACTION ISOLATION LEVEl [READ COMMITTED/REPEATABLE READ/SERIALIZABLE];  --一次启动事务并指定事务隔离级别
BEGIN;
TRANSACTION ISOLATION LEVEl [READ COMMITTED/REPEATABLE READ/SERIALIZABLE];  --先启动事务,再设置事务隔离级别
  • 结束事务
commit
rollback
  • 预备事务
--预备事务,使得事务分阶段可以提交
PREPARE TRANSACTION 'foobar';
......
COMMIT PREPARE TRANSACTION 'foobar';
ROLLBACK PREPARE TRANSACTION 'foobar';
  • 保存点
--保存点savepoint,可以支持事务的部分回滚
insert into lyy values(1,'nn');
savepoint svp1;
insert into lyy values(2,'ff');
rollback to savepoint svp1;
--此时提交的话,第二个insert未被插入,但是第一个插入成功。
  • 查看当前事务的事务id
select  txid_current();

详情参考:https://my.oschina.net/liuyuanyuangogo/blog/415395

其他参考

pg锁机制理解:http://francs3.blog.163.com/blog/static/40576727201082134343604/
mysql锁机制理解: http://hedengcheng.com/?p=771
pg中mvcc实现机制:http://www.zlovezl.cn/articles/postgresql-concurrency-with-mvcc/
http://blog.itpub.net/30088583/viewspace-1585695/
较好的阐释了pg中mvcc的原理:https://my.oschina.net/Kenyon/blog/108850
pg事务级别查看与变更:http://blog.csdn.net/scugxl/article/details/51126433
mysql与pg对比:https://www.sdk.cn/news/4587
pg维护vacuum解析:http://www.cnblogs.com/stephen-liu74/archive/2011/12/27/2304155.html
Ubuntu安装PG与使用:http://wenzhixin.net.cn/2014/01/12/hello_postgresql

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容