Fix locking for serializing chunk creation

Chunk creation needs to be serialized in order
to avoid having multiple processes trying to
create the same chunk and causing conflicts.

This serialization didn't work as expected, because
a lock on the chunk catalog table that implemented
this serialization was prematurely released.

This change fixes that issue and also changes the
serialization to happen around a lock on the
chunk's parent table (the main table) instead. This
change should allow multiple processes to simultaneously
create chunks for different hypertables.
This commit is contained in:
Erik Nordström 2018-01-25 21:47:20 +01:00 committed by Erik Nordström
parent 6dd2c46c94
commit 5afd39a6ba

View File

@ -15,6 +15,7 @@
#include <utils/lsyscache.h> #include <utils/lsyscache.h>
#include <utils/syscache.h> #include <utils/syscache.h>
#include <utils/hsearch.h> #include <utils/hsearch.h>
#include <storage/lmgr.h>
#include <miscadmin.h> #include <miscadmin.h>
#include "chunk.h" #include "chunk.h"
@ -466,8 +467,8 @@ chunk_create_after_lock(Hypertable *ht, Point *p, const char *schema, const char
snprintf(chunk->fd.table_name.data, NAMEDATALEN, snprintf(chunk->fd.table_name.data, NAMEDATALEN,
"%s_%d_chunk", prefix, chunk->fd.id); "%s_%d_chunk", prefix, chunk->fd.id);
/* Insert chunk. Chunk table already locked in exclusive mode. */ /* Insert chunk */
chunk_insert_lock(chunk, NoLock); chunk_insert_lock(chunk, RowExclusiveLock);
/* Insert any new dimension slices */ /* Insert any new dimension slices */
dimension_slice_insert_multi(cube->slices, cube->num_slices); dimension_slice_insert_multi(cube->slices, cube->num_slices);
@ -501,11 +502,15 @@ chunk_create_after_lock(Hypertable *ht, Point *p, const char *schema, const char
Chunk * Chunk *
chunk_create(Hypertable *ht, Point *p, const char *schema, const char *prefix) chunk_create(Hypertable *ht, Point *p, const char *schema, const char *prefix)
{ {
Catalog *catalog = catalog_get();
Chunk *chunk; Chunk *chunk;
Relation rel;
rel = heap_open(catalog->tables[CHUNK].id, ExclusiveLock); /*
* Serialize chunk creation around a lock on the "main table" to avoid
* multiple processes trying to create the same chunk. We use a
* ShareUpdateExclusiveLock, which is the weakest lock possible that
* conflicts with itself. The lock needs to be held until transaction end.
*/
LockRelationOid(ht->main_table_relid, ShareUpdateExclusiveLock);
/* Recheck if someone else created the chunk before we got the table lock */ /* Recheck if someone else created the chunk before we got the table lock */
chunk = chunk_find(ht->space, p); chunk = chunk_find(ht->space, p);
@ -513,8 +518,6 @@ chunk_create(Hypertable *ht, Point *p, const char *schema, const char *prefix)
if (NULL == chunk) if (NULL == chunk)
chunk = chunk_create_after_lock(ht, p, schema, prefix); chunk = chunk_create_after_lock(ht, p, schema, prefix);
heap_close(rel, ExclusiveLock);
Assert(chunk != NULL); Assert(chunk != NULL);
return chunk; return chunk;