Cayenne "resets" primary key value? - mysql

I am using Cayenne to add records to a MySQL database, and I am seeing some strange behavior.
When I run my application, I create a DataContext, perform a series of adds, then close the application. This works out well, because I am using an integer for a primary key, and when I add a record to the database, the key automatically increments. For some reason, it starts at 200 for the first record, then goes to 201 for the second record, etc.
If, however, I stop the application, then run it again, the primary key starts at 200 again! This, of course, causes an exception to be thrown because a new record ends up having a duplicate primary key. It is looking like when I create a new object using the DataContext's newObject() after starting my application, Cayenne does not "remember" how far the primary key was incremented when the application was previously run.
Does anyone know what is causing this reset of the primary key values, and (more importantly) how to stop it from happening??? Or have I found a bug in the current version of Cayenne? I am using Version 3.0.2.
Someone please advise...

The last used PK for a given table is stored in a special table called AUTO_PK_SUPPORT. Please check the contents of this table between the restarts of your app. Also check you application Cayenne logs for reads and writes to AUTO_PK_SUPPORT. This should give you an idea of what's happening.
Aside from that you might switch to auto-increment PK (see "Primary Key Provided by Database" section here). MySQL supports auto-incremented PK columns and if you have an option of altering the schema, this IMO is the cleanest PK generation strategy out of all available. (And it doesn't require AUTO_PK_SUPPORT).

Related

Duplicate entry for key 'PRIMARY' - even though it is set to AUTO_INCREMENT

Bit of a strange one - I haven't changed the config, database, PHP code for this site for about 8 years. The whole time the guy I made it for has been adding, removing, changing stock with no issue, and suddenly today gets this error:
Duplicate entry '2541' for key 'PRIMARY'
executing (inserted generic values for the texts):
INSERT INTO stock (id,title,category,description,price,last_update,sold) VALUES(NULL,'Item name','72','Item description','0',1613723525,'no')
Searching around seemed to suggest this was a common problem when the primary key is not set to auto increment - makes sense. However, checking it out through phpMyAdmin, it definitely is.
Is there something in the index being set to primary rather than unique?
There are 5 other tables on the database but none are linked (as in hard links through the SQL, PHP handles all the cross-table stuff).
I checked and indeed there IS an item in the stock table with ID 2541 already. So why is that NULL AUTO_INCREMENT value converting to an existing id?
EDIT
I noticed that a table I created more recently (via MySQL Workbench probably) has a different setup for the indexes, with the addition of an id_UNIQUE index - do I need one of these on the stock table that is causing issues?
Based on your description and your comment "Interestingly, each time I refresh the ID it is attempted to insert (and failing on) increments by 1", I suspect that somehow the seed for the autoincrement for that table got changed to some value that was inserted at some time before.
How exactly that could happen I don't know.
Now, each time you attempt to insert a record this internal counter increments, so you see in the error message that the number increases (2541, 2542, ...) When you attempt to insert a row the internal counter increments regardless of whether the transaction is committed to the database or not. In your case the insert operation is rolled back, because the generated value violates the unique constraint and the internal counter keeps growing.
To change the seed you can run the following statement:
ALTER TABLE stock AUTO_INCREMENT=1234567;
You'll need to set it to the current MAX value that exists in the table, so that new entries that the system attempts to insert do not conflict.
See also How to set initial value and auto increment in MySQL?
This answer shows how to change the autoincrement seed in MySQL Workbench and in PhpMyAdmin. Maybe somebody did this accidentally and didn't notice.

Rails: ActiveRecord::UnknownPrimaryKey exception

A ActiveRecord::UnknownPrimaryKey occurred in survey_response#create:
Unknown primary key for table question_responses in model QuestionResponse.
activerecord (3.2.8) lib/active_record/reflection.rb:366:in `primary_key'
Our application has been raising these exceptions and we do not know what is causing them. The exception happens in both production and test environments, but it is not reproducible in either. It seems to have some relation to server load, but even in times of peak loads some of the requests still complete successfully. The app (both production and test environments) is Rails 3.2.8, ruby 1.9.3-p194 using MySQL with the mysql2 gem. Production is Ubuntu and dev/test is OS X. The app is running under Phusion Passenger in production.
Here is a sample stack trace: https://gist.github.com/4068400
Here are the two models in question, the controller and the output of "desc question_responses;": https://gist.github.com/4b3667a6896b60383dc3
It most definitely has a primary key, which is a standard rails 'id' column.
Restarting the app server temporarily stops the exceptions from occurring, otherwise they happen over a period of time 30 minutes - 6 hours in length, starting as suddenly as they stop.
It always occurs on the same controller action, table and model.
Has anyone else run into this exception?
FWIW, I was getting this same intermittent error and after a heck of a lot of head-scratching I found the cause.
We have separate DBs per client, and some how one of the client's DBs had a missing primary key on the users table. This meant that when that client accessed our site, Rails updated it's in-memory schema to that of the database it had connected to, with the missing primary key. Any future requests served by that Passenger app process (or any others that had been 'infected' by this client) which tried to access the users table borked out with the primary key error, regardless of whether that particular database had a primary key.
In the end a fairly self-explanatory error, but difficult to pin down when you've got 500+ databases and only one of them was causing the problem, and it was intermittent.
Got this problem because my workers used shared connection to database. But I was on unicorn.
I know that Passenger reconnects by default, but maybe you have some complicated logic. Connections to number of databases, for example. So you need to reconnect all connections.
This same thing happened to me. I had a composite primary key in one of my table definitions which caused the error. It was further compounded because annotate models did not (but will shortly / does now) support annotation of composite primary keys.
My solution was to make the id column the only primary key and add a constraint (not shown) for the composition. To do this you need to drop auto_increment on id if this is set, drop your composite primary key, then re-add both the primary status and autoincrement.
ALTER TABLE indices MODIFY id INT NOT NULL;
ALTER TABLE indices DROP PRIMARY KEY;
ALTER TABLE indices MODIFY id INT NOT NULL PRIMARY KEY AUTO_INCREMENT;
on postgres database
ALTER TABLE indices ALTER COLUMN id SET DATA TYPE INT;
ALTER TABLE indices ADD PRIMARY KEY (id)

Relationship issue in the MySql designer

Normally I have no issue with MySQL's PHPmyadmin designer to create referential integrity relations.
All of a sudden, I now get a 99% Loading in my browser window, and a popup php.
Reproduce;
Select a database.
Select designer.
Select 'Set Relation'
Select a primary key
Select a coresponding foriegn key
Approve confirmation
Expected results; (and what I usually get)
A relationship is setup.
A line connecting two keys.
Actual results;
a green label "Loading 99%" appears in upper right corner.
a second window pops up http://localhost/phpmyadmin/pmd_general.php?db=jobhunt&server=1&token=d8235.....
Relationship does not occur.
Is anyone else getting this?
Yep, it was happening with me too. I've made some attempts here and discovered that the error of the blank pop-up occurs because I was trying to make a relationship with a foreign key that has no index set up.
Create an index for the future foreign key column and that may resolve.
Pay attention that when you try to make the relation without the index, the confirm box that appears has just a "Ok" and "Cancel" button, while when you already have the index, it permits you to set up the behaviors on delete and on update.
[Solved] Just update Java for Windows plugin for your browser (Firefox, Chrome...)
Go to Java site and update Java Firefox plugin.
One more solution is install and use SQLyog;
While I still do not know why the interface decided to break but an add Forien Key works fine.
ALTER TABLE tableblah
add FOREIGN KEY FCK2-BLAH ([Foreign-Key column]) REFERENCES [primary key table]([primary key column]);
This method works for me:
1. Select table and click on Operations.
2. Change Storage Engine in table option to InnoDB.
3. Hit "Go" button.
Now, you can add foreign key by adding INDEX on column.

MS Access "duplicate values" error, but I don't know why

I have a VB6 program that adds a column to an MS Access database thusly:
alter table x add column y long constraint z unique
The program goes through a number of databases without error; however, on the one that I am looking at now, it gives me "The changes you requested to the table were not successful because they would create duplicate values in the index, primary key, or relationship..."
In case it makes a difference, I add values to the column by forming a recordset of the primary key and new column values, then going through each record to add a value to this column. I do recordSet.updateBatch when I'm all done.
If I remove the constraint, it completes normally; I have put all 1600 values into a spreadsheet, sorted by the values I've added, and used a formula to check for duplicates. There aren't any. All rows get a new value, none of the new values are the same as any other new value.
Are there other reasons why I might get this error? I really don't want to remove the constraint, but I don't know how to get past this.
Since you're certain you're not attempting to insert rows which violate the table's index constraints, perhaps you have a corrupted index. See whether Compact & Repair cures the problem. But first make a backup of the database.
You could also recreate the table in a new database and test it there.
You can find further information about corruption at Tony Towes' Corrupt Microsoft Access MDBs FAQ.

Foreign key in SQL Server 2008 pointing to another database

How can I add a constraint that references a foreign column from another database?
Some time ago I read that it can be done with linked server and others say with triggers. What's the preferred way of doing this if that's possible at all?
Thanks!
Linked servers will not work.
FK's must point to local tables.
The preferred way is not to do this, though you can pull a few hacks to make it happen.
For example you could have triggers cause the reference to be created/checked but I wouldn't consider that equivalent to a FK constraint.
Related question:
Can you have a Foreign Key onto a View of a Linked Server table in SQLServer 2k5?
Use an instead of trigger (you may or may not need linked servers depending on whether the other database is on a differnt server). Make sure the trigger can handle multiple row inserts/updates/deletes. I'd also suggest moving the records that fail the check to an exception table.
Foreign keys cannot go across database boundaries. If you try to do this, you'll get:
Msg 1763, Level 16, State 0, Line 1
Cross-database foreign key
references are not supported. Foreign key ***
Msg 1750, Level 16, State 0, Line 1
Could not create constraint. See previous errors.
If you need to enforce some kind of relationship between two separate databases, then yes - you might need a linked server (if that second database is on a second server), and possibly triggers - but all of those things will be very hard to get right, very inefficient and very error prone.
One way you might be able to do this would be data replication - replicate the table you want to reference into your source database, and then establish a foreign key relationship with that replicated table. But that will never be quite "live" and "real-time" - there will also be a bit of a lag in the data replication.