MariaDB 10.2.10 Slave stops on duplicate key error - mariadb

I've been setting up two Debian Stretch based MariaDB-Server in Master-Master-Replication.
Slave's replication config section is:
server-id = 2226
auto_increment_increment = 1
auto_increment_offset = 1
log_bin = /var/tmp/mysql_binlog/mysql-bin.log
log_bin_index = /var/tmp/mysql_binlog/mysql-bin.log.index
expire_logs_days = 3
max_binlog_size = 100M
relay_log = /var/tmp/mysql_binlog/slave-relay.log
relay_log_index = /var/tmp/mysql_binlog/slave-relay.log.index
log_slave_updates = 1
replicate_annotate_row_events = 0
log_bin_trust_function_creators = 1
I am experiencing the following error:
show slave status\G;
Relay_Log_File: slave-relay.032025
Relay_Log_Pos: 14887746
Relay_Master_Log_File: mysql-bin.001119
Slave_IO_Running: Yes
Last_Errno: 1062
Last_Error: Error 'Duplicate entry '71899-single' for key 'PRIMARY'' on query. Default database: 'mydb'. Query: 'INSERT INTO document_reference
(document_reference_document_id, document_reference_type, document_reference_value)
VALUES (71899, "single", 0)'
but:
MariaDB [(none)]> select * from mydb.document_reference WHERE document_reference_document_id=71899;
Empty set (0.00 sec)
I've looked up the relay log file - there is only one insert statement.
Anyone has an idea what causes duplicate entry error on slave?
Added information:
Master settings:
auto_increment_increment | 1
auto_increment_offset | 1
binlog_format | MIXED
Table definition:
CREATE TABLE "document_reference" (
"document_reference_document_id" int(10) unsigned NOT NULL,
"document_reference_type" enum('single,'multi') COLLATE utf8_unicode_ci
NOT NULL DEFAULT 'single',
"document_reference_value" int(11) NOT NULL,
PRIMARY KEY ("document_reference_document_id","document_reference_type"))

When having "dual Master", set
auto_increment_increment = 2 -- on both
auto_increment_offset = 1 on one Master, = 2 on the other
Also, server_id must be different on the two Masters (and on any Slaves). If they are not different, replication goes round and round between the Masters.
Otherwise, inserts on separate Masters can generate the same AUTO_INCREMENT values.
However, that does not answer the problem. (There is no auto_inc involved.) The only possible answer (I think) is that two of these rows: (71899, "single", ...) were inserted. The absence of evidence of such in the SELECT may have to do with DELETEs, deadlocks, etc. (So, I do not have a definite answer.)

Related

MARIADB sequences - incrementing by 2

I have the following MARIADB code. It's supposed to demonstrate:
Constructing tables using sequences for incrementing the ID.
Using a temporary table+join to INSERT data into a table, while incrementing the ID.
Procedure:
Sequence S1 and table T1 are created. T1_ID is incremented with S1
Sequence S2 and table T2 are created. T2_ID is incremented with S2
Table T1 is filled with data. All is fine.
Temporary table TEMP_T2 is created and filled with data. No ID in this table. Column T1_NAME is a cross reference to SHORT_NAME in table T1.
The T1_ID is introduced into table TEMP_T2 with a join. The result of this SELECT is inserted into T2. Here, the sequence S2 should auto-increment T2_ID.
For some reason, at the end, T2 looks like this:
T2_ID|T1_ID|NAME|
-----+-----+----+
2| 1|y |
4| 2|x |
6| 2|z |
Why was T2_ID double-incremented?
Thanks!
USE DB1;
SET FOREIGN_KEY_CHECKS = 0;
DROP SEQUENCE IF EXISTS `S2`;
DROP SEQUENCE IF EXISTS `S1`;
DROP TABLE IF EXISTS `T2`;
DROP TABLE IF EXISTS `T1`;
-- Create sequence S1 and able T1
CREATE SEQUENCE `S1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB;
SELECT SETVAL(`S1`, 1, 0);
CREATE TABLE `T1` (
`T1_ID` tinyint(4) NOT NULL DEFAULT nextval(`S1`),
`SHORT_NAME` varchar(10) NOT NULL,
PRIMARY KEY (`T1_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
-- Create sequence T2 and table T2
CREATE SEQUENCE `S2` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB;
SELECT SETVAL(`S2`, 1, 0);
CREATE TABLE `T2` (
`T2_ID` int(11) NOT NULL DEFAULT nextval(`S2`),
`T1_ID` int(11) DEFAULT NULL,
`NAME` varchar(100) DEFAULT NULL COLLATE 'utf8mb3_bin',
PRIMARY KEY (`T2_ID`),
UNIQUE KEY `T2_NAME_UN` (`NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
-- Load data into T1
DELETE FROM T1;
INSERT INTO T1(SHORT_NAME) VALUES
('a'),
('b'),
('c');
SELECT * FROM T1;
-- Create temporary file for joining with T1
DROP TABLE IF EXISTS `TEMP_T2`;
CREATE TEMPORARY TABLE `TEMP_T2` (
`T1_NAME` varchar(10) DEFAULT NULL,
`NAME` varchar(100) DEFAULT NULL,
UNIQUE KEY `T2_NAME_UN` (`NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
DELETE FROM TEMP_T2 ;
-- Insert data into the temporary table
INSERT INTO TEMP_T2(T1_NAME,NAME) VALUES
('b','x'),
('a','y'),
('b','z');
SELECT * FROM TEMP_T2;
# Do a join with TEMP_T2 x T1 and insert into T2
INSERT INTO T2(T1_ID,NAME)
SELECT
t1.T1_ID ,
t2.NAME
FROM TEMP_T2 AS t2
INNER JOIN T1 AS t1
ON t2.T1_NAME =t1.SHORT_NAME ;
SELECT * FROM T2;
Thanks for the responses.
I'm using SEQUENCE rather than AUTO_INCREMENT because I was told that it is the more modern way. It also enables retrieving the last ID of any specific table.
It's strange that this should be a bug. It seems like really basic functionality. But so it is...
I've found this as a reported existing bug MDEV-29540 in INSERT ... SELECT as it pertains to sequences in default values of columns.
Because this bug is reported and fix, this problem is/will not occur in the 10.3.37, 10.4.27, 10.5.18, 10.6.11, 10.7.7, 10.8.6, 10.9.4, 10.10.2, 10.11.1 and later versions.

How to insert data from R into Oracle table with identity column?

Assume I have a simple table in Oracle db
CREATE TABLE schema.d_test
(
id_record integer GENERATED AS IDENTITY START WITH 95000 NOT NULL,
DT DATE NOT NULL,
var varchar(50),
num float,
PRIMARY KEY (ID_RECORD)
)
And I have a dataframe in R
dt = c('2022-01-01', '2005-04-01', '2011-10-02')
var = c('sgdsg', 'hjhgjg', 'rurtur')
num = c(165, 1658.5, 8978.12354)
data = data.frame(dt, var, num)%>%
mutate(dt = as.Date(dt))
I'm trying to insert data into Oracle d_test table using the code
data %>%
dbWriteTable(
oracle_con,
value = .,
date = T,
'D_TEST',
append = T,
row.names=F,
overwrite = F
)
But the following error returned
Error in .oci.WriteTable(conn, name, value, row.names = row.names, overwrite = overwrite, :
Error in .oci.GetQuery(con, stmt, data = value) :
ORA-00947: not enough values
What's the problem?
How can I fix it?
Thank you.
This is pure Oracle (I don't know R).
Sample table:
SQL> create table test_so (id number generated always as identity not null, name varchar2(20));
Table created.
SQL> insert into test_so(name) values ('Name 1');
1 row created.
My initial idea was to suggest you to insert any value into the ID column, hoping that Oracle would discard it and generate its own value. However, that won't work.
SQL> insert into test_so (id, name) values (-100, 'Name 2');
insert into test_so (id, name) values (-100, 'Name 2')
*
ERROR at line 1:
ORA-32795: cannot insert into a generated always identity column
But, if you can afford recreating the table so that it doesn't automatically generate the ID column's value but use a "workaround" (we used anyway, as identity columns are relatively new in Oracle) - a sequence and a trigger - you might be able to "fix" it.
SQL> drop table test_so;
Table dropped.
SQL> create table test_so (id number not null, name varchar2(20));
Table created.
SQL> create sequence seq_so;
Sequence created.
SQL> create or replace trigger trg_bi_so
2 before insert on test_so
3 for each row
4 begin
5 :new.id := seq_so.nextval;
6 end;
7 /
Trigger created.
Inserting only name (Oracle will use a trigger to populate ID):
SQL> insert into test_so(name) values ('Name 1');
1 row created.
This is what you'll do in your code - provide dummy ID value, just to avoid
ORA-00947: not enough values
error you have now. Trigger will discard it and use sequence anyway:
SQL> insert into test_so (id, name) values (-100, 'Name 2');
1 row created.
SQL> select * from test_so;
ID NAME
---------- --------------------
1 Name 1
2 Name 2 --> this is a row which was supposed to have ID = -100
SQL>
The way you can handle this problem is to create table with GENERATED BY DEFAULT ON NULL AS IDENTITY like this
CREATE TABLE CM_RISK.d_test
(
id_record integer GENERATED BY DEFAULT ON NULL AS IDENTITY START WITH 5000 NOT NULL ,
DT date NOT NULL,
var varchar(50),
num float,
PRIMARY KEY (ID_RECORD)
)

create virtual column in mariadb with case statement fails

I am trying to create a table in MariaDB with a virtual column, defined by a case statement
This is what I have
create table Foto (
ID int AUTO_INCREMENT not null primary key,
LigPlaatsCode varchar(10) not null,
FotoTypeID int not null check (FotoType in (0, 1, 2, 3)),
Foto varchar(1000) not null,
FotoType varchar(50) as
case FotoTypeID
when 0 then 'Bidprent'
when 1 then 'Krantartikel'
when 2 then 'Persoon'
else 'Graf'
end, `
constraint FK_Foto_LigPlaats foreign key (LigPlaatsCode) references LigPlaats (LigPlaatsCode)
)
however it always gives me this error
#42000You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use
near 'case FotoTypeID
when 0 then 'Bidprent'
when 1 then 'Krantar' at line 7
When I google on how to create virtual column and case, the links I found seem to suggest I got it right, but obviously I dont. So I am missing something.
What is wrong with this create table statement ?
EDIT
my version is 10.3.21-MariaDB
Generated column requires parantehese around case expression:
create table Foto (
ID int AUTO_INCREMENT not null primary key,
LigPlaatsCode varchar(10) not null,
FotoTypeID int not null ,
Foto varchar(1000) not null,
FotoType varchar(50) as
(case FotoTypeID
when 0 then 'Bidprent'
when 1 then 'Krantartikel'
when 2 then 'Persoon'
else 'Graf'
end), -- brackets around
-- constraint as separate entry because it is referencing FotoType
constraint fototypecheck check (FotoType in (0, 1, 2, 3))
);
db<>fiddle demo
This line does not make sense as FotoType is text:
FotoTypeID int not null check (FotoType in (0, 1, 2, 3)),
-- probably it should be
FotoTypeID int not null check (FotoTypeID in (0, 1, 2, 3)),

How to append to SQLite table in R with autogenerated fields

This is a similar problem to this question, but I do not want the missing columns filled in with NA, because the missing columns have meaningful default values including the primary key.
I am trying to append to a SQLite table from R where the table has some auto-generated fields, specifically the primary key, and two timestamp values. The first timestamp is the created date, and the second timestamp is a modified date.
Here is the table structure:
CREATE TABLE "level1" (
"l1id" bigint(20) NOT NULL ,
"l0id" bigint(20) DEFAULT NULL,
"acid" bigint(20) DEFAULT NULL,
"cndx" int(11) DEFAULT NULL,
"repi" int(11) DEFAULT NULL,
"created_date" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"modified_date" timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
"modified_by" varchar(100) DEFAULT NULL,
PRIMARY KEY ("l1id")
)
When I have tried doing the exact same thing using MySQL, dbWriteTable automatically handles the default values for missing columns, and populates the primary key and created_date properly (AND it matches the order of the columns automatically).
How can I achieve the same behavior with the RSQLite package? I am not sure if I have the database configured incorrectly, or if I need some addtional steps within R?
I have tried pre-populating the missing fields with NA & 'null', but in both cases I get an error saying:
Warning message:
In value[[3L]](cond) :
RS-DBI driver: (RS_SQLite_exec: could not execute: column l1id is not unique)
And the data does not get written.
The Solution
I figured out a solution, based largely on the dbWriteFactor function Ari Friedman wrote as an answer to his question. Below I show the portion of code I used, modified to work specifically with the data.table package.
It is also very important to note that I had to change the sqlite table structure. To get this to work I had to remove the "NOT NULL" designation from all auto-generated fields.
New Table Structure
CREATE TABLE "level1" (
"l1id" INTEGER PRIMARY KEY,
"l0id" bigint(20) DEFAULT NULL,
"acid" bigint(20) DEFAULT NULL,
"cndx" int(11) DEFAULT NULL,
"repi" int(11) DEFAULT NULL,
"created_date" timestamp DEFAULT CURRENT_TIMESTAMP,
"modified_date" timestamp DEFAULT '0000-00-00 00:00:00',
"modified_by" varchar(100) DEFAULT NULL
);
Adapted Code Sample
dbcon <- do.call(dbConnect, db_pars)
tempTbl <- "temp_table"
if (dbExistsTable(dbcon, tempTbl)) dbRemoveTable(dbcon, tempTbl)
dbWriteTable(conn = dbcon,
name = tempTbl,
value = dat,
row.names = FALSE,
append = FALSE)
tbl_flds <- loadColNames(tbl, db)
tmp_flds <- names(dat)
status <- dbSendQuery(dbcon,
paste("INSERT INTO", tbl,
"(", paste(tmp_flds, collapse = ","), ")",
"SELECT",
paste(tmp_flds, collapse = ","),
"FROM",
tempTbl))
# Remove temporary table
dbRemoveTable(dbcon, tempTbl)
dbDisconnect(dbcon)
where db_pars is a list of database parameters to establish the connection.

How to use join query to fetch data from more than two tables without foreign key and primary key

Once I need your help,
I have three table in my database.
1> wedding
Column Name Data Type
-------------------------------------
wedID Int (primary key)
wedName varchar (50)
2> selectSite
Column Name Data Type
-----------------------------------
wedID Int (without foreign key and primary key with null allow)
siteID Int (without foreign key and primary key with null allow)
siteStatus varchar(50)
3> webSite
Column Name Data Type
--------------------------------
siteID Int (Primary Key)
siteName varchar(50)
siteFile varchar(MAX)
I want the following output:
ws.siteID ws.siteName ws.siteFile s.wedID s.sitestatus
----------------------------------------------------------------------------
1 Show show.jpeg 6 Yes
2 My View my view.png 5
3 Dream dream.jpeg 3
ws is alias of webSite table, s is alias of siteSelect table.
All data from webSite table and only data from siteSelect where s.siteStatus do not display Yes if wedID not match
I try following sql query
select
DISTINCT(ws.siteID), s.wedID, ws.siteName,
ws.siteFile, s.siteStatus
from wedding wd, webSite ws
left outer join siteSelect s on ws.siteID = s.siteID
where wd.wedID = #wedID
but output is like this:
ws.siteID ws.siteName ws.siteFile s.wedID s.sitestatus
-----------------------------------------------------------------------
1 Show show.jpeg 6 Yes
2 My View my view.png 5 Yes
3 Dream dream.jpeg 3 Yes
DEMO SQL FIDDLE
Check the demo add some values as you having and run this query
select
ws.siteId, ws.siteName, ws.siteFile, ss.wedID,
(case
when ss.wedID = 1 then ss.siteStatus else '' end) as siteStatus
from
website ws
join
selectsite ss on ss.siteID=ws.siteID
let me knw if any prob
try this
select
DISTINCT(ws.siteID), s.wedID, ws.siteName, ws.siteFile,
(case
when s.wedID = #wedID
then s.siteStatus
else '' end) as siteStatus, wd.wedName
from webSite ws
left join selectSite s on ws.siteID = s.siteID
Left Join wedding wd on wd.wedID = s.wedID

Resources