mirror of https://github.com/citusdata/citus.git
Deprecate enable_deadlock_prevention flag
Now that we already have the necessary infrastructure for detecting distributed deadlocks. Thus, we don't need enable_deadlock_prevention which is purely intended for preventing some forms of distributed deadlocks.pull/1529/head
parent
a333c9f16c
commit
be4fc45c03
|
@ -70,6 +70,8 @@
|
||||||
|
|
||||||
/* controls use of locks to enforce safe commutativity */
|
/* controls use of locks to enforce safe commutativity */
|
||||||
bool AllModificationsCommutative = false;
|
bool AllModificationsCommutative = false;
|
||||||
|
|
||||||
|
/* we've deprecated this flag, keeping here for some time not to break existing users */
|
||||||
bool EnableDeadlockPrevention = true;
|
bool EnableDeadlockPrevention = true;
|
||||||
|
|
||||||
/* functions needed during run phase */
|
/* functions needed during run phase */
|
||||||
|
@ -79,8 +81,7 @@ static ShardPlacementAccess * CreatePlacementAccess(ShardPlacement *placement,
|
||||||
static void ExecuteSingleModifyTask(CitusScanState *scanState, Task *task,
|
static void ExecuteSingleModifyTask(CitusScanState *scanState, Task *task,
|
||||||
bool expectResults);
|
bool expectResults);
|
||||||
static void ExecuteSingleSelectTask(CitusScanState *scanState, Task *task);
|
static void ExecuteSingleSelectTask(CitusScanState *scanState, Task *task);
|
||||||
static List * GetModifyConnections(Task *task, bool markCritical,
|
static List * GetModifyConnections(Task *task, bool markCritical);
|
||||||
bool startedInTransaction);
|
|
||||||
static void ExecuteMultipleTasks(CitusScanState *scanState, List *taskList,
|
static void ExecuteMultipleTasks(CitusScanState *scanState, List *taskList,
|
||||||
bool isModificationQuery, bool expectResults);
|
bool isModificationQuery, bool expectResults);
|
||||||
static int64 ExecuteModifyTasks(List *taskList, bool expectResults,
|
static int64 ExecuteModifyTasks(List *taskList, bool expectResults,
|
||||||
|
@ -680,8 +681,6 @@ ExecuteSingleModifyTask(CitusScanState *scanState, Task *task, bool expectResult
|
||||||
|
|
||||||
char *queryString = task->queryString;
|
char *queryString = task->queryString;
|
||||||
bool taskRequiresTwoPhaseCommit = (task->replicationModel == REPLICATION_MODEL_2PC);
|
bool taskRequiresTwoPhaseCommit = (task->replicationModel == REPLICATION_MODEL_2PC);
|
||||||
bool startedInTransaction =
|
|
||||||
InCoordinatedTransaction() && XactModificationLevel == XACT_MODIFICATION_DATA;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Modifications for reference tables are always done using 2PC. First
|
* Modifications for reference tables are always done using 2PC. First
|
||||||
|
@ -711,9 +710,7 @@ ExecuteSingleModifyTask(CitusScanState *scanState, Task *task, bool expectResult
|
||||||
* establish the connection, mark as critical (when modifying reference
|
* establish the connection, mark as critical (when modifying reference
|
||||||
* table) and start a transaction (when in a transaction).
|
* table) and start a transaction (when in a transaction).
|
||||||
*/
|
*/
|
||||||
connectionList = GetModifyConnections(task,
|
connectionList = GetModifyConnections(task, taskRequiresTwoPhaseCommit);
|
||||||
taskRequiresTwoPhaseCommit,
|
|
||||||
startedInTransaction);
|
|
||||||
|
|
||||||
/* prevent replicas of the same shard from diverging */
|
/* prevent replicas of the same shard from diverging */
|
||||||
AcquireExecutorShardLock(task, operation);
|
AcquireExecutorShardLock(task, operation);
|
||||||
|
@ -809,12 +806,10 @@ ExecuteSingleModifyTask(CitusScanState *scanState, Task *task, bool expectResult
|
||||||
* modify commands on the placements in tasPlacementList. If necessary remote
|
* modify commands on the placements in tasPlacementList. If necessary remote
|
||||||
* transactions are started.
|
* transactions are started.
|
||||||
*
|
*
|
||||||
* If markCritical is true remote transactions are marked as critical. If
|
* If markCritical is true remote transactions are marked as critical.
|
||||||
* noNewTransactions is true, this function errors out if there's no
|
|
||||||
* transaction in progress.
|
|
||||||
*/
|
*/
|
||||||
static List *
|
static List *
|
||||||
GetModifyConnections(Task *task, bool markCritical, bool noNewTransactions)
|
GetModifyConnections(Task *task, bool markCritical)
|
||||||
{
|
{
|
||||||
List *taskPlacementList = task->taskPlacementList;
|
List *taskPlacementList = task->taskPlacementList;
|
||||||
ListCell *taskPlacementCell = NULL;
|
ListCell *taskPlacementCell = NULL;
|
||||||
|
@ -844,22 +839,17 @@ GetModifyConnections(Task *task, bool markCritical, bool noNewTransactions)
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If already in a transaction, disallow expanding set of remote
|
* If we're expanding the set nodes that participate in the distributed
|
||||||
* transactions. That prevents some forms of distributed deadlocks.
|
* transaction, conform to MultiShardCommitProtocol.
|
||||||
*/
|
*/
|
||||||
if (noNewTransactions)
|
if (MultiShardCommitProtocol == COMMIT_PROTOCOL_2PC &&
|
||||||
|
InCoordinatedTransaction() &&
|
||||||
|
XactModificationLevel == XACT_MODIFICATION_DATA)
|
||||||
{
|
{
|
||||||
RemoteTransaction *transaction = &multiConnection->remoteTransaction;
|
RemoteTransaction *transaction = &multiConnection->remoteTransaction;
|
||||||
|
if (transaction->transactionState == REMOTE_TRANS_INVALID)
|
||||||
if (EnableDeadlockPrevention &&
|
|
||||||
transaction->transactionState == REMOTE_TRANS_INVALID)
|
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errcode(ERRCODE_CONNECTION_DOES_NOT_EXIST),
|
CoordinatedTransactionUse2PC();
|
||||||
errmsg("no transaction participant matches %s:%d",
|
|
||||||
taskPlacement->nodeName, taskPlacement->nodePort),
|
|
||||||
errdetail("Transactions which modify distributed tables "
|
|
||||||
"may only target nodes affected by the "
|
|
||||||
"modification command which began the transaction.")));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ void _PG_init(void);
|
||||||
|
|
||||||
static void CreateRequiredDirectories(void);
|
static void CreateRequiredDirectories(void);
|
||||||
static void RegisterCitusConfigVariables(void);
|
static void RegisterCitusConfigVariables(void);
|
||||||
|
static void WarningForEnableDeadlockPrevention(bool newval, void *extra);
|
||||||
static void NormalizeWorkerListPath(void);
|
static void NormalizeWorkerListPath(void);
|
||||||
|
|
||||||
|
|
||||||
|
@ -379,7 +380,7 @@ RegisterCitusConfigVariables(void)
|
||||||
true,
|
true,
|
||||||
PGC_USERSET,
|
PGC_USERSET,
|
||||||
GUC_NO_SHOW_ALL,
|
GUC_NO_SHOW_ALL,
|
||||||
NULL, NULL, NULL);
|
NULL, WarningForEnableDeadlockPrevention, NULL);
|
||||||
|
|
||||||
DefineCustomBoolVariable(
|
DefineCustomBoolVariable(
|
||||||
"citus.enable_ddl_propagation",
|
"citus.enable_ddl_propagation",
|
||||||
|
@ -737,6 +738,18 @@ RegisterCitusConfigVariables(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inform the users about the deprecated flag.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
WarningForEnableDeadlockPrevention(bool newval, void *extra)
|
||||||
|
{
|
||||||
|
ereport(WARNING, (errcode(ERRCODE_WARNING_DEPRECATED_FEATURE),
|
||||||
|
errmsg("citus.enable_deadlock_prevention is deprecated and it has "
|
||||||
|
"no effect. The flag will be removed in the next release.")));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NormalizeWorkerListPath converts the path configured via
|
* NormalizeWorkerListPath converts the path configured via
|
||||||
* citus.worker_list_file into an absolute path, falling back to the default
|
* citus.worker_list_file into an absolute path, falling back to the default
|
||||||
|
|
|
@ -145,18 +145,18 @@ SELECT * FROM researchers, labs WHERE labs.id = researchers.lab_id;
|
||||||
8 | 5 | Douglas Engelbart | 5 | Los Alamos
|
8 | 5 | Douglas Engelbart | 5 | Los Alamos
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
-- but not the other way around (would require expanding xact participants)...
|
-- and the other way around is also allowed
|
||||||
BEGIN;
|
BEGIN;
|
||||||
INSERT INTO labs VALUES (6, 'Bell Labs');
|
INSERT INTO labs VALUES (6, 'Bell Labs');
|
||||||
INSERT INTO researchers VALUES (9, 6, 'Leslie Lamport');
|
INSERT INTO researchers VALUES (9, 6, 'Leslie Lamport');
|
||||||
ERROR: no transaction participant matches localhost:57638
|
|
||||||
DETAIL: Transactions which modify distributed tables may only target nodes affected by the modification command which began the transaction.
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
-- unless we disable deadlock prevention
|
-- we should be able to expand the transaction participants
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SET citus.enable_deadlock_prevention TO off;
|
|
||||||
INSERT INTO labs VALUES (6, 'Bell Labs');
|
INSERT INTO labs VALUES (6, 'Bell Labs');
|
||||||
INSERT INTO researchers VALUES (9, 6, 'Leslie Lamport');
|
INSERT INTO researchers VALUES (9, 6, 'Leslie Lamport');
|
||||||
|
ERROR: duplicate key value violates unique constraint "avoid_name_confusion_idx_1200001"
|
||||||
|
DETAIL: Key (lab_id, name)=(6, Leslie Lamport) already exists.
|
||||||
|
CONTEXT: while executing command on localhost:57638
|
||||||
ABORT;
|
ABORT;
|
||||||
-- SELECTs may occur after a modification: First check that selecting
|
-- SELECTs may occur after a modification: First check that selecting
|
||||||
-- from the modified node works.
|
-- from the modified node works.
|
||||||
|
@ -165,7 +165,7 @@ INSERT INTO labs VALUES (6, 'Bell Labs');
|
||||||
SELECT count(*) FROM researchers WHERE lab_id = 6;
|
SELECT count(*) FROM researchers WHERE lab_id = 6;
|
||||||
count
|
count
|
||||||
-------
|
-------
|
||||||
0
|
1
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
ABORT;
|
ABORT;
|
||||||
|
@ -181,7 +181,7 @@ INSERT INTO labs VALUES (6, 'Bell Labs');
|
||||||
SELECT count(*) FROM researchers WHERE lab_id = 6;
|
SELECT count(*) FROM researchers WHERE lab_id = 6;
|
||||||
count
|
count
|
||||||
-------
|
-------
|
||||||
0
|
1
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
ABORT;
|
ABORT;
|
||||||
|
@ -205,8 +205,9 @@ SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.labs'::
|
||||||
|
|
||||||
SELECT * FROM labs WHERE id = 6;
|
SELECT * FROM labs WHERE id = 6;
|
||||||
id | name
|
id | name
|
||||||
----+------
|
----+-----------
|
||||||
(0 rows)
|
6 | Bell Labs
|
||||||
|
(1 row)
|
||||||
|
|
||||||
-- COPY can happen after single row INSERT
|
-- COPY can happen after single row INSERT
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
@ -273,8 +274,9 @@ COMMIT;
|
||||||
-- verify rollback
|
-- verify rollback
|
||||||
SELECT * FROM researchers WHERE lab_id = 6;
|
SELECT * FROM researchers WHERE lab_id = 6;
|
||||||
id | lab_id | name
|
id | lab_id | name
|
||||||
----+--------+------
|
----+--------+----------------
|
||||||
(0 rows)
|
9 | 6 | Leslie Lamport
|
||||||
|
(1 row)
|
||||||
|
|
||||||
SELECT count(*) FROM pg_dist_transaction;
|
SELECT count(*) FROM pg_dist_transaction;
|
||||||
count
|
count
|
||||||
|
@ -300,8 +302,9 @@ COMMIT;
|
||||||
-- verify rollback
|
-- verify rollback
|
||||||
SELECT * FROM researchers WHERE lab_id = 6;
|
SELECT * FROM researchers WHERE lab_id = 6;
|
||||||
id | lab_id | name
|
id | lab_id | name
|
||||||
----+--------+------
|
----+--------+----------------
|
||||||
(0 rows)
|
9 | 6 | Leslie Lamport
|
||||||
|
(1 row)
|
||||||
|
|
||||||
SELECT count(*) FROM pg_dist_transaction;
|
SELECT count(*) FROM pg_dist_transaction;
|
||||||
count
|
count
|
||||||
|
@ -317,9 +320,10 @@ COMMIT;
|
||||||
SELECT * FROM researchers WHERE lab_id = 6;
|
SELECT * FROM researchers WHERE lab_id = 6;
|
||||||
id | lab_id | name
|
id | lab_id | name
|
||||||
----+--------+----------------------
|
----+--------+----------------------
|
||||||
|
9 | 6 | Leslie Lamport
|
||||||
17 | 6 | 'Bjarne Stroustrup'
|
17 | 6 | 'Bjarne Stroustrup'
|
||||||
18 | 6 | 'Dennis Ritchie'
|
18 | 6 | 'Dennis Ritchie'
|
||||||
(2 rows)
|
(3 rows)
|
||||||
|
|
||||||
-- verify 2pc
|
-- verify 2pc
|
||||||
SELECT count(*) FROM pg_dist_transaction;
|
SELECT count(*) FROM pg_dist_transaction;
|
||||||
|
@ -376,9 +380,10 @@ ERROR: could not commit transaction on any active node
|
||||||
SELECT * FROM researchers WHERE lab_id = 6;
|
SELECT * FROM researchers WHERE lab_id = 6;
|
||||||
id | lab_id | name
|
id | lab_id | name
|
||||||
----+--------+----------------------
|
----+--------+----------------------
|
||||||
|
9 | 6 | Leslie Lamport
|
||||||
17 | 6 | 'Bjarne Stroustrup'
|
17 | 6 | 'Bjarne Stroustrup'
|
||||||
18 | 6 | 'Dennis Ritchie'
|
18 | 6 | 'Dennis Ritchie'
|
||||||
(2 rows)
|
(3 rows)
|
||||||
|
|
||||||
-- cleanup triggers and the function
|
-- cleanup triggers and the function
|
||||||
SELECT * from run_command_on_placements('researchers', 'drop trigger reject_large_researcher_id on %s')
|
SELECT * from run_command_on_placements('researchers', 'drop trigger reject_large_researcher_id on %s')
|
||||||
|
@ -429,7 +434,7 @@ ALTER TABLE labs ADD COLUMN motto text;
|
||||||
SELECT master_modify_multiple_shards('DELETE FROM labs');
|
SELECT master_modify_multiple_shards('DELETE FROM labs');
|
||||||
master_modify_multiple_shards
|
master_modify_multiple_shards
|
||||||
-------------------------------
|
-------------------------------
|
||||||
7
|
8
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
ALTER TABLE labs ADD COLUMN score float;
|
ALTER TABLE labs ADD COLUMN score float;
|
||||||
|
@ -909,16 +914,13 @@ SELECT create_distributed_table('hash_modifying_xacts', 'key');
|
||||||
BEGIN;
|
BEGIN;
|
||||||
INSERT INTO hash_modifying_xacts VALUES (1, 1);
|
INSERT INTO hash_modifying_xacts VALUES (1, 1);
|
||||||
INSERT INTO reference_modifying_xacts VALUES (10, 10);
|
INSERT INTO reference_modifying_xacts VALUES (10, 10);
|
||||||
ERROR: no transaction participant matches localhost:57638
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
-- it is allowed when turning off deadlock prevention
|
-- it is allowed when turning off deadlock prevention
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SET citus.enable_deadlock_prevention TO off;
|
|
||||||
INSERT INTO hash_modifying_xacts VALUES (1, 1);
|
INSERT INTO hash_modifying_xacts VALUES (1, 1);
|
||||||
INSERT INTO reference_modifying_xacts VALUES (10, 10);
|
INSERT INTO reference_modifying_xacts VALUES (10, 10);
|
||||||
ABORT;
|
ABORT;
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SET citus.enable_deadlock_prevention TO off;
|
|
||||||
INSERT INTO hash_modifying_xacts VALUES (1, 1);
|
INSERT INTO hash_modifying_xacts VALUES (1, 1);
|
||||||
INSERT INTO hash_modifying_xacts VALUES (2, 2);
|
INSERT INTO hash_modifying_xacts VALUES (2, 2);
|
||||||
ABORT;
|
ABORT;
|
||||||
|
|
|
@ -136,12 +136,10 @@ SELECT * FROM researchers_mx, labs_mx WHERE labs_mx.id = researchers_mx.lab_id;
|
||||||
8 | 5 | Douglas Engelbart | 5 | Los Alamos
|
8 | 5 | Douglas Engelbart | 5 | Los Alamos
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
-- but not the other way around (would require expanding xact participants)...
|
-- and the other way around is also allowed
|
||||||
BEGIN;
|
BEGIN;
|
||||||
INSERT INTO labs_mx VALUES (6, 'Bell labs_mx');
|
INSERT INTO labs_mx VALUES (6, 'Bell labs_mx');
|
||||||
INSERT INTO researchers_mx VALUES (9, 6, 'Leslie Lamport');
|
INSERT INTO researchers_mx VALUES (9, 6, 'Leslie Lamport');
|
||||||
ERROR: no transaction participant matches localhost:57638
|
|
||||||
DETAIL: Transactions which modify distributed tables may only target nodes affected by the modification command which began the transaction.
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
-- have the same test on the other worker node
|
-- have the same test on the other worker node
|
||||||
\c - - - :worker_2_port
|
\c - - - :worker_2_port
|
||||||
|
@ -159,12 +157,10 @@ SELECT * FROM researchers_mx, labs_mx WHERE labs_mx.id = researchers_mx.lab_id;
|
||||||
8 | 5 | Douglas Engelbart | 5 | Los Alamos
|
8 | 5 | Douglas Engelbart | 5 | Los Alamos
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
-- but not the other way around (would require expanding xact participants)...
|
-- and the other way around is also allowed
|
||||||
BEGIN;
|
BEGIN;
|
||||||
INSERT INTO labs_mx VALUES (6, 'Bell labs_mx');
|
INSERT INTO labs_mx VALUES (6, 'Bell labs_mx');
|
||||||
INSERT INTO researchers_mx VALUES (9, 6, 'Leslie Lamport');
|
INSERT INTO researchers_mx VALUES (9, 6, 'Leslie Lamport');
|
||||||
ERROR: no transaction participant matches localhost:57638
|
|
||||||
DETAIL: Transactions which modify distributed tables may only target nodes affected by the modification command which began the transaction.
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
-- switch back to the worker node
|
-- switch back to the worker node
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
|
@ -175,7 +171,7 @@ INSERT INTO labs_mx VALUES (6, 'Bell labs_mx');
|
||||||
SELECT count(*) FROM researchers_mx WHERE lab_id = 6;
|
SELECT count(*) FROM researchers_mx WHERE lab_id = 6;
|
||||||
count
|
count
|
||||||
-------
|
-------
|
||||||
0
|
2
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
ABORT;
|
ABORT;
|
||||||
|
|
|
@ -113,15 +113,14 @@ COMMIT;
|
||||||
|
|
||||||
SELECT * FROM researchers, labs WHERE labs.id = researchers.lab_id;
|
SELECT * FROM researchers, labs WHERE labs.id = researchers.lab_id;
|
||||||
|
|
||||||
-- but not the other way around (would require expanding xact participants)...
|
-- and the other way around is also allowed
|
||||||
BEGIN;
|
BEGIN;
|
||||||
INSERT INTO labs VALUES (6, 'Bell Labs');
|
INSERT INTO labs VALUES (6, 'Bell Labs');
|
||||||
INSERT INTO researchers VALUES (9, 6, 'Leslie Lamport');
|
INSERT INTO researchers VALUES (9, 6, 'Leslie Lamport');
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
-- unless we disable deadlock prevention
|
-- we should be able to expand the transaction participants
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SET citus.enable_deadlock_prevention TO off;
|
|
||||||
INSERT INTO labs VALUES (6, 'Bell Labs');
|
INSERT INTO labs VALUES (6, 'Bell Labs');
|
||||||
INSERT INTO researchers VALUES (9, 6, 'Leslie Lamport');
|
INSERT INTO researchers VALUES (9, 6, 'Leslie Lamport');
|
||||||
ABORT;
|
ABORT;
|
||||||
|
@ -703,13 +702,11 @@ COMMIT;
|
||||||
|
|
||||||
-- it is allowed when turning off deadlock prevention
|
-- it is allowed when turning off deadlock prevention
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SET citus.enable_deadlock_prevention TO off;
|
|
||||||
INSERT INTO hash_modifying_xacts VALUES (1, 1);
|
INSERT INTO hash_modifying_xacts VALUES (1, 1);
|
||||||
INSERT INTO reference_modifying_xacts VALUES (10, 10);
|
INSERT INTO reference_modifying_xacts VALUES (10, 10);
|
||||||
ABORT;
|
ABORT;
|
||||||
|
|
||||||
BEGIN;
|
BEGIN;
|
||||||
SET citus.enable_deadlock_prevention TO off;
|
|
||||||
INSERT INTO hash_modifying_xacts VALUES (1, 1);
|
INSERT INTO hash_modifying_xacts VALUES (1, 1);
|
||||||
INSERT INTO hash_modifying_xacts VALUES (2, 2);
|
INSERT INTO hash_modifying_xacts VALUES (2, 2);
|
||||||
ABORT;
|
ABORT;
|
||||||
|
|
|
@ -118,7 +118,7 @@ COMMIT;
|
||||||
|
|
||||||
SELECT * FROM researchers_mx, labs_mx WHERE labs_mx.id = researchers_mx.lab_id;
|
SELECT * FROM researchers_mx, labs_mx WHERE labs_mx.id = researchers_mx.lab_id;
|
||||||
|
|
||||||
-- but not the other way around (would require expanding xact participants)...
|
-- and the other way around is also allowed
|
||||||
BEGIN;
|
BEGIN;
|
||||||
INSERT INTO labs_mx VALUES (6, 'Bell labs_mx');
|
INSERT INTO labs_mx VALUES (6, 'Bell labs_mx');
|
||||||
INSERT INTO researchers_mx VALUES (9, 6, 'Leslie Lamport');
|
INSERT INTO researchers_mx VALUES (9, 6, 'Leslie Lamport');
|
||||||
|
@ -134,7 +134,7 @@ COMMIT;
|
||||||
|
|
||||||
SELECT * FROM researchers_mx, labs_mx WHERE labs_mx.id = researchers_mx.lab_id;
|
SELECT * FROM researchers_mx, labs_mx WHERE labs_mx.id = researchers_mx.lab_id;
|
||||||
|
|
||||||
-- but not the other way around (would require expanding xact participants)...
|
-- and the other way around is also allowed
|
||||||
BEGIN;
|
BEGIN;
|
||||||
INSERT INTO labs_mx VALUES (6, 'Bell labs_mx');
|
INSERT INTO labs_mx VALUES (6, 'Bell labs_mx');
|
||||||
INSERT INTO researchers_mx VALUES (9, 6, 'Leslie Lamport');
|
INSERT INTO researchers_mx VALUES (9, 6, 'Leslie Lamport');
|
||||||
|
|
Loading…
Reference in New Issue