- 論壇徽章:
- 3
|
數(shù)據(jù)庫的事務(wù)隔離級(jí)別有4種:
READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ
SERIALIZABLE
而在PostgreSQL事務(wù)隔離級(jí)別中,READ UNCOMMITTED是之間被認(rèn)為是READ COMMITTED,所以實(shí)際上只有三種。
PostgreSQL默認(rèn)隔離級(jí)別是READ COMMTIED,而MySQL默認(rèn)為REPEATABLE READ,另MySQL是有READ UNCOMMITTED這種級(jí)別的,不過一般這種事務(wù)隔離級(jí)別基本上沒有什么用。
MySQL 在REPEATABLE READ隔離級(jí)別下,普通的select語句是看不到在事務(wù)啟動(dòng)之后已經(jīng)提交的數(shù)據(jù),但select for update卻能看到,也就是說普通select與select for update看到的結(jié)果是不一樣的,這是特別需要讓開發(fā)人員注意的地方。
而PostgreSQL在REPEATABLE READ隔離級(jí)別,select for udpate語句和select語句的結(jié)果是一樣的,都看不到在事務(wù)啟動(dòng)之后已經(jīng)提交的數(shù)據(jù)。
另MySQL有一個(gè)很奇怪的間隙鎖,如果表中的數(shù)據(jù)為(1,2,3,10,11),如果執(zhí)行select * from t1 where id=6 for update;加鎖后,其它的用戶將不能插入(4,5,6,7,8,9)的主鍵值了;如果select for update鎖住一個(gè)主鍵值比表中現(xiàn)有主鍵值還大的一個(gè)值時(shí),則此表就不能插入比表中主鍵值更大的鍵值了。
下面演示一下:
在PostgreSQL中建測(cè)試表和數(shù)據(jù):
osdba=# create table t1(id int primary key, info text);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t1_pkey" for table "t1"
CREATE TABLE
osdba=# insert into t1 values(1,'11111');
INSERT 0 1
osdba=# insert into t1 values(2,'22222');
INSERT 0 1
osdba=# insert into t1 values(3,'33333');
INSERT 0 1
osdba=# insert into t1 values(10,'101010');
INSERT 0 1
osdba=# insert into t1 values(11,'111111');
osdba=# select * from t1;
id | info
----+--------
1 | 11111
2 | 22222
3 | 33333
10 | 101010
11 | 111111
(5 rows)
在MySQL中建測(cè)試數(shù)據(jù):
mysql> create table t1(id int primary key, info varchar(255));
Query OK, 0 rows affected (0.13 sec)
mysql> insert into t1 values(1,'11111');
Query OK, 1 row affected (0.03 sec)
mysql> insert into t1 values(2,'22222');
Query OK, 1 row affected (0.04 sec)
mysql> insert into t1 values(3,'33333');
Query OK, 1 row affected (0.05 sec)
mysql> insert into t1 values(10,'101010');
Query OK, 1 row affected (0.04 sec)
mysql> select * from t1;
+----+--------+
| id | info |
+----+--------+
| 1 | 11111 |
| 2 | 22222 |
| 3 | 33333 |
| 10 | 101010 |
| 11 | 111111 |
+----+--------+
5 rows in set (0.00 sec)
先測(cè)試PostgreSQL:
在窗口1中,在“REPEATABLE READ”啟動(dòng)一個(gè)事務(wù):
osdba=# begin isolation level REPEATABLE READ ;
BEGIN
在窗口2中,往表插入一條記錄:
osdba=# insert into t1 values(5,'555555');
INSERT 0 1
然后再回到窗口1中:
osdba=# select * from t1 where id=5;
id | info
----+------
(0 rows)
osdba=# select * from t1 where id=5 for update;
id | info
----+------
(0 rows)
可以看到在PostgreSQL中不管是select語句不管加不加for update,看到的結(jié)果都是一樣的,都看不到id=5記錄。
而MySQL是不一樣的,MySQL的普通select 語句是看不到id=5的記錄,但select for update卻能看到,見下面:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t1 where id=5;
Empty set (0.00 sec)
mysql> select * from t1 where id=5 for update;
+----+-------+
| id | info |
+----+-------+
| 5 | 55555 |
+----+-------+
1 row in set (0.00 sec)
mysql>
可以看到MySQL在REPEATABLE READ隔的級(jí)別下,看到的select for update與普通的select 看到的結(jié)果是不一樣的。
在MySQL中,一旦設(shè)置了SERIALIZABLE級(jí)別后,在事務(wù)中一旦查詢表,就會(huì)把查詢的記錄都鎖住,而PostgreSQL中的SERIALIZABLE也與MySQL中完全不一樣。查詢不會(huì)鎖表。
在PostgreSQL中,在窗口1中先開始一個(gè)事務(wù),然后在窗口2中再開始一個(gè)事務(wù),窗口2中修改id=3的記錄,再到窗口1中修改id=3的記錄時(shí),會(huì)報(bào)錯(cuò),由此實(shí)現(xiàn)了SERIALIZABLE的隔離級(jí)別。
由此可見在SERIALIZABLE的級(jí)別上,PostGreSQL的并發(fā)會(huì)比MySQL好很多。 |
|