【问题标题】:Why Cassandra does not give error on inserting duplicate record?为什么 Cassandra 在插入重复记录时不会出错?
【发布时间】:2021-06-29 09:16:23
【问题描述】:

CQL 版本 5.0.1

Cassandra 版本 3.11.9

root@3fdb49de030c:/# cqlsh
Connected to Test Cluster at 127.0.0.1:1234.
[cqlsh 5.0.1 | Cassandra 3.11.9 | CQL spec 3.4.4 | Native protocol v4]
Use HELP for help.
cqlsh>

在插入相同记录时(如下图),

cqlsh> use mykeyspace;
cqlsh:mykeyspace>
cqlsh:mykeyspace>
cqlsh:mykeyspace>
cqlsh:mykeyspace>
cqlsh:mykeyspace> select * from mytable ;

 column1                              | column2                              | column3                         | column4           | column5                      | column6
--------------------------------------+--------------------------------------+---------------------------------+-------------------+---------------------------------+--------------
 54dc8b12-a934-4f2e-8a0d-e7eba3faa47e | 587df674-bc77-481b-b974-ddebd203e371 | 2021-04-02 13:29:37.841000+0000 | sample@abc.com | 2021-04-02 13:29:37.841000+0000 | [{"abc": "def"}]

(1 rows)
cqlsh:mykeyspace>
cqlsh:mykeyspace>
cqlsh:mykeyspace>
cqlsh:mykeyspace> // does not give error on changin non-primary key columns
cqlsh:mykeyspace> INSERT  INTO   mytable (column1, column2, column4, column6, column3, column5)   VALUES (54dc8b12-a934-4f2e-8a0d-e7eba3faa47e,  587df674-bc77-481b-b974-ddebd203e371, 'sample@abc.com', 'xyz',toTimestamp(now()),toTimestamp(now()));
cqlsh:mykeyspace>
cqlsh:mykeyspace>
cqlsh:mykeyspace> select * from mytable ;
    
     column1                              | column2                              | column3                         | column4           | column5                      | column6
    --------------------------------------+--------------------------------------+---------------------------------+-------------------+---------------------------------+--------------
     54dc8b12-a934-4f2e-8a0d-e7eba3faa47e | 587df674-bc77-481b-b974-ddebd203e371 | 2021-04-02 13:29:37.841000+0000 | sample@abc.com | 2021-04-02 13:29:37.841000+0000 | xyz
    
    (1 rows)
cqlsh:mykeyspace>
cqlsh:mykeyspace>
cqlsh:mykeyspace>
cqlsh:mykeyspace>
cqlsh:mykeyspace>
cqlsh:mykeyspace> // does not give error on changing one of the  primary key column
cqlsh:mykeyspace> INSERT  INTO   mytable (column1, column2, column4, column6, column3, column5)   VALUES (54dc8b12-a934-4f2e-8a0d-e7eba3faa47e,  587df674-bc77-481b-b974-ddebd203e372, 'garbage', 'garbage',toTimestamp(now()),toTimestamp(now()));
cqlsh:mykeyspace>
cqlsh:mykeyspace>
cqlsh:mykeyspace>
cqlsh:mykeyspace> select * from mytable ; // PK(column1:column2)

 column1                              | column2                              | column3                         | column4           | column5                         | column6
--------------------------------------+--------------------------------------+---------------------------------+---------------+---------------------------------+-----------------------
 54dc8b12-a934-4f2e-8a0d-e7eba3faa47e | 587df674-bc77-481b-b974-ddebd203e371 | 2020-04-02 14:20:24.028000+0000 |    sample@abc.com | 2020-04-02 14:20:24.028000+0000 |               xyz
 54dc8b12-a934-4f2e-8a0d-e7eba3faa47e | 587df674-bc77-481b-b974-ddebd203e372 | 2020-04-02 14:26:55.101000+0000 |           garbage | 2020-04-02 14:26:55.101000+0000 |           garbage

(2 rows)
cqlsh:mykeyspace>
cqlsh:mykeyspace>
cqlsh:mykeyspace>
cqlsh:mykeyspace> DESCRIBE TABLE mytable;

CREATE TABLE mykeyspace.mytable (
    column1 uuid,
    column2 uuid,
    column3 timestamp,
    column4 text,
    column5 timestamp,
    column6 text,
    PRIMARY KEY (column1, column2)
)WITH CLUSTERING ORDER BY (column2 ASC)
    AND bloom_filter_fp_chance = 0.01
    AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}
    AND comment = ''
    AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'}
    AND compression = {'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND crc_check_chance = 1.0
    AND dclocal_read_repair_chance = 0.1
    AND default_time_to_live = 0
    AND gc_grace_seconds = 864000
    AND max_index_interval = 2048
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND read_repair_chance = 0.0
    AND speculative_retry = '99PERCENTILE';

cqlsh:mykeyspace>
cqlsh:mykeyspace>
cqlsh:mykeyspace>

Cassandra 在插入重复记录(具有相同的主键)时是否不显示错误? 而是更新记录

如果否,如何在使用 gocql 插入相同记录时错误处理重复记录?对于 http POST 请求...我们还没有使用幂等密钥

RDBMS SQL server 给出类似Cannot insert duplicate key row的错误

【问题讨论】:

    标签: sql http cassandra cql gocql


    【解决方案1】:

    不幸的是,Cassandra 以其“锋利的边缘”而闻名,这就是其中之一。

    Cassandra 没有发现 INSERTUPDATE 之间的区别。它们本质上是相同的。提供的键指示数据应写入的位置,基于日志的存储引擎将其放置在那里。这意味着您实际上可以使用INSERT 执行更新,并使用UPDATE 执行插入。

    要按照您所描述的方式工作,Cassandra 必须知道所提供键的值是否已经存在。做到这一点的唯一方法是首先读取这些键处的数据,然后然后写入它。在并发、高吞吐量的分布式数据场景中,这样做并不安全,因为在完成读取和执行写入之间可能会发生另一次写入。

    如果您需要这种行为,您可以使用IF [NOT] EXISTS 条件调用lightweight transaction

    INSERT  INTO   mytable (column1, column2, column4, column6, column3, column5)
    VALUES (54dc8b12-a934-4f2e-8a0d-e7eba3faa47e,  587df674-bc77-481b-b974-ddebd203e371, 'sample@abc.com', 'xyz',toTimestamp(now()),toTimestamp(now()))
    IF NOT EXISTS;
    

    这实质上是在幕后执行先读后写,因此确实会影响性能。

    【讨论】:

    • 这是任何数据库的基本功能(预期)。为什么 Cassandra 如此受欢迎?就因为它可以水平缩放?
    • @overexchange Cassandra 没有很多“预期”的功能,因为它的设计者将性能置于安全之上。 Cassandra 的初始版本甚至没有授权。顺便说一句,你真的应该使用。
    猜你喜欢
    • 1970-01-01
    • 2017-05-13
    • 2011-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-10
    • 1970-01-01
    • 2023-01-23
    相关资源
    最近更新 更多