注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

PostgreSQL 中文网

 
 
 

日志

 
 

PostgreSQL MVCC: future transaction should not be visible to the current transaction  

2012-05-05 21:51:26|  分类: Postgres基础 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

 
 
          之前在读到手册 "Preventing Transaction ID Wraparound Failures" 时,一直有段话不太明白,这段话内容如下:
今天在听德哥培训课时,终于理解了,德哥原BLOG: http://blog.163.com/digoal@126/blog/static/163877040201183043153622/
今天参考德哥BLOG 做了下测试,终于明白了以下手册内容。
 

--手册内容的一段话
              PostgreSQL's MVCC transaction semantics depend on being able to compare transaction ID (XID) numbers:
a row version with an insertion XID greater than the current transaction's XID is "in the future" and should
not be visible to the current transaction

    备注:要理解这段话,首先得知道每行记录插入时 pg 会分配给每行 tuple 一个 xid, 这个 xid 为系统隐含字段 xmin,
              那么任何比 xmin 值要大的事务被认为是将来的,而且将来的事务在当前事务中不可见;这样翻译有点难懂,下面
              做下实验就清楚了。

 

实验一:验证未来事务在当前事务不可见
--1.1 创建测试表并插入三条记录

 mydb=> create table test_29 (id integer,name varchar(32));
CREATE TABLE

mydb=> insert into test_29 values (1,'a');
INSERT 0 1
mydb=> insert into test_29 values (2,'b');
INSERT 0 1
mydb=> insert into test_29 values (3,'c');
INSERT 0 1

   


--1.2 查询记录的 xmin

 mydb=> select xmin,*,txid_current() from test_29;
 xmin | id | name | txid_current
------+----+------+--------------
 3338 |  1 | a    |         3341
 3339 |  2 | b    |         3341
 3340 |  3 | c    |         3341
(3 rows)

mydb=> select txid_current();
 txid_current
--------------
         3342
(1 row)

mydb=> select txid_current();
 txid_current
--------------
         3343
(1 row)

   


--1.3 再次插入三条记录,并查询记录 xmin

 mydb=> insert into test_29 values (4,'d');
INSERT 0 1
mydb=> insert into test_29 values (5,'e');
INSERT 0 1
mydb=> insert into test_29 values (6,'f');
INSERT 0 1

mydb=> select xmin,*,txid_current() from test_29;
 xmin | id | name | txid_current
------+----+------+--------------
 3338 |  1 | a    |         3347
 3339 |  2 | b    |         3347
 3340 |  3 | c    |         3347
 3344 |  4 | d    |         3347
 3345 |  5 | e    |         3347
 3346 |  6 | f    |         3347
(6 rows)

 备注:注意记录的 xmin 值。

 
   
 
 
--1.4 查看控制文件:pg_controldata 输出

 [postgres@pgb ~]$ pg_controldata
pg_control version number:            903
Catalog version number:               201105231
Database system identifier:           5652547536925883229
Database cluster state:               in production
pg_control last modified:             Wed 02 May 2012 09:27:56 PM CST
Latest checkpoint location:           1/BC000020
Prior checkpoint location:            1/B8015934
Latest checkpoint's REDO location:    1/BC000020
Latest checkpoint's TimeLineID:       5
Latest checkpoint's NextXID:          0/3336
Latest checkpoint's NextOID:          66605
Latest checkpoint's NextMultiXactId:  1
Latest checkpoint's NextMultiOffset:  0
Latest checkpoint's oldestXID:        1670
Latest checkpoint's oldestXID's DB:   16386
Latest checkpoint's oldestActiveXID:  0
Time of latest checkpoint:            Wed 02 May 2012 09:26:34 PM CST
Minimum recovery ending location:     0/0
Backup start location:                0/0
Current wal_level setting:            hot_standby
Current max_connections setting:      100
Current max_prepared_xacts setting:   0
Current max_locks_per_xact setting:   64
Maximum data alignment:               4
Database block size:                  8192
Blocks per segment of large relation: 1048576
WAL block size:                       65536
Bytes per WAL segment:                67108864
Maximum length of identifiers:        64
Maximum columns in an index:          32
Maximum size of a TOAST chunk:        2000
Date/time type storage:               64-bit integers
Float4 argument passing:              by value
Float8 argument passing:              by reference

   备注:Latest checkpoint s NextXID:值为 3336

   


--1.5 关闭 PostgreSQL

 [postgres@pgb ~]$ pg_ctl stop -m fast -D $PGDATA
waiting for server to shut down...... done
server stopped
   

 

--1.6 再次查看 pg_controldata

 pg_control version number:            903
Catalog version number:               201105231
Database system identifier:           5652547536925883229
Database cluster state:               shut down
pg_control last modified:             Wed 02 May 2012 09:29:34 PM CST
Latest checkpoint location:           1/C0000020
Prior checkpoint location:            1/BC000020
Latest checkpoint's REDO location:    1/C0000020
Latest checkpoint's TimeLineID:       5
Latest checkpoint's NextXID:          0/3348
Latest checkpoint's NextOID:          66608
Latest checkpoint's NextMultiXactId:  1
Latest checkpoint's NextMultiOffset:  0
Latest checkpoint's oldestXID:        1670
Latest checkpoint's oldestXID's DB:   16386
Latest checkpoint's oldestActiveXID:  0
Time of latest checkpoint:            Wed 02 May 2012 09:29:32 PM CST
Minimum recovery ending location:     0/0
Backup start location:                0/0
Current wal_level setting:            hot_standby
Current max_connections setting:      100
Current max_prepared_xacts setting:   0
Current max_locks_per_xact setting:   64
Maximum data alignment:               4
Database block size:                  8192
Blocks per segment of large relation: 1048576
WAL block size:                       65536
Bytes per WAL segment:                67108864
Maximum length of identifiers:        64
Maximum columns in an index:          32
Maximum size of a TOAST chunk:        2000
Date/time type storage:               64-bit integers
Float4 argument passing:              by value
Float8 argument passing:              by reference

 备注: Latest checkpoint s NextXID:     值发生了变化,值为 3348,这是因为关闭数据库时
                触发了 checkpoint。

   


--1.7 我们尝试把 NextXID 设置成  3341 ,看看会出现什么情况   

 [postgres@pgb ~]$ pg_resetxlog -x 3341 $PGDATA
Transaction log reset
[postgres@pgb ~]$ pg_ctl start -D $PGDATA
server starting     
 
   


--1.8 再次查询

 [postgres@pgb ~]$ psql -h 127.0.0.1 mydb mydb
psql (9.1.0)
Type "help" for help.

mydb=> select xmin,*,txid_current() from test_29;
 xmin | id | name | txid_current
------+----+------+--------------
 3338 |  1 | a    |         3341
 3339 |  2 | b    |         3341
 3340 |  3 | c    |         3341
(3 rows)

mydb=> select xmin,*,txid_current() from test_29;
 xmin | id | name | txid_current
------+----+------+--------------
 3338 |  1 | a    |         3342
 3339 |  2 | b    |         3342
 3340 |  3 | c    |         3342
(3 rows)

mydb=> select xmin,*,txid_current() from test_29;
 xmin | id | name | txid_current
------+----+------+--------------
 3338 |  1 | a    |         3343
 3339 |  2 | b    |         3343
 3340 |  3 | c    |         3343
(3 rows)

mydb=> select xmin,*,txid_current() from test_29;
 xmin | id | name | txid_current
------+----+------+--------------
 3338 |  1 | a    |         3344
 3339 |  2 | b    |         3344
 3340 |  3 | c    |         3344
(3 rows)

   

 备注:上面一直只能查看到 test_29 表的前三条记录,后三条记录消失,那是因为后三条记录的
            xmin 大于 3344,而当前事务ID 小于或等于 3344,所以后三条记录对于当前事务来说是未来的,
            所以在当前事务中不可见,接着查询看会出现什么情况。

 mydb=> select xmin,*,txid_current() from test_29;
 xmin | id | name | txid_current
------+----+------+--------------
 3338 |  1 | a    |         3345
 3339 |  2 | b    |         3345
 3340 |  3 | c    |         3345
 3344 |  4 | d    |         3345
(4 rows)

mydb=> select xmin,*,txid_current() from test_29;
 xmin | id | name | txid_current
------+----+------+--------------
 3338 |  1 | a    |         3347
 3339 |  2 | b    |         3347
 3340 |  3 | c    |         3347
 3344 |  4 | d    |         3347
 3345 |  5 | e    |         3347
 3346 |  6 | f    |         3347
(6 rows)

   

   备注:随着当前事务号的增加,后面的三条记录居然出现了。
  
  
        按照上面 PostgreSQL MVCC 原理,那么可以模拟下数据库因为 Transaction ID Wraparound  失败,而造成
  所有数据消失的情况。
 
实验二:模拟事务 "Transaction ID Wraparound" 失败,所有数据消失

--2.1 操作前数据库信息

 [postgres@pgb ~]$ psql -h 127.0.0.1 mydb mydb
psql (9.1.0)
Type "help" for help.

mydb=> \dt
            List of relations
 Schema |      Name      | Type  | Owner
--------+----------------+-------+-------
 mydb   | ad_position_ad | table | mydb
 mydb   | array_test     | table | mydb
 mydb   | phone          | table | mydb
 mydb   | phone_201202   | table | mydb
 mydb   | test           | table | mydb
 mydb   | test_10        | table | mydb
 mydb   | test_11        | table | mydb
 mydb   | test_12        | table | mydb
 mydb   | test_13        | table | mydb
 mydb   | test_14        | table | mydb
 mydb   | test_15        | table | mydb
 mydb   | test_16        | table | mydb
 mydb   | test_17        | table | mydb
 mydb   | test_18        | table | mydb
 mydb   | test_19        | table | mydb
 mydb   | test_2         | table | mydb
 mydb   | test_20        | table | mydb
 mydb   | test_21        | table | mydb
 mydb   | test_23        | table | mydb
 mydb   | test_24        | table | mydb
 mydb   | test_25        | table | mydb
 mydb   | test_26        | table | mydb
 mydb   | test_27        | table | mydb
 mydb   | test_28        | table | mydb
 mydb   | test_29        | table | mydb
 mydb   | test_3         | table | mydb
 mydb   | test_4         | table | mydb
 mydb   | test_5         | table | mydb
 mydb   | test_6         | table | mydb
 mydb   | test_7         | table | mydb
 mydb   | test_8         | table | mydb
 mydb   | test_9         | table | mydb
 mydb   | test_array     | table | mydb
 mydb   | test_integer   | table | mydb
 mydb   | test_name      | table | mydb
 mydb   | test_standby   | table | mydb
 mydb   | test_unlogged  | table | mydb
 mydb   | test_user      | table | mydb
(38 rows)

   


--2.2 pg_controldata 输出

 [postgres@pgb ~]$ pg_controldata
pg_control version number:            903
Catalog version number:               201105231
Database system identifier:           5652547536925883229
Database cluster state:               in production
pg_control last modified:             Sat 05 May 2012 09:25:43 PM CST
Latest checkpoint location:           1/C4000270
Prior checkpoint location:            1/C4000020
Latest checkpoint's REDO location:    1/C4000240
Latest checkpoint's TimeLineID:       5
Latest checkpoint's NextXID:          0/3348
Latest checkpoint's NextOID:          66608
Latest checkpoint's NextMultiXactId:  1
Latest checkpoint's NextMultiOffset:  0
Latest checkpoint's oldestXID:        1670
Latest checkpoint's oldestXID's DB:   16386
Latest checkpoint's oldestActiveXID:  3348
Time of latest checkpoint:            Sat 05 May 2012 09:25:43 PM CST
Minimum recovery ending location:     0/0
Backup start location:                0/0
Current wal_level setting:            hot_standby
Current max_connections setting:      100
Current max_prepared_xacts setting:   0
Current max_locks_per_xact setting:   64
Maximum data alignment:               4
Database block size:                  8192
Blocks per segment of large relation: 1048576
WAL block size:                       65536
Bytes per WAL segment:                67108864
Maximum length of identifiers:        64
Maximum columns in an index:          32
Maximum size of a TOAST chunk:        2000
Date/time type storage:               64-bit integers
Float4 argument passing:              by value
Float8 argument passing:              by reference
   

--2.3 关闭数据库

 [postgres@pgb ~]$ pg_ctl stop -m fast -D $PGDATA
waiting for server to shut down...... done
server stopped
   


--2.4 重置 xid,设置较小的 xid

 [postgres@pgb ~]$ pg_resetxlog -x 100 $PGDATA
Transaction log reset
   

 备注:这里将 xid 重置成 100, 看下接下来会发生什么情况。
 

--2.5 重启数据库并查看

 [postgres@pgb ~]$ psql -h 127.0.0.1 mydb mydb
psql (9.1.0)
Type "help" for help.

mydb=> \dt
No relations found.

mydb=> select txid_current();
 txid_current
--------------
          100
(1 row)

   

备注:所有表消失。

  评论这张
 
阅读(26680)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2016