MySQL movie reservation system design part 2 - mysql

This is similar to another question but not entirely the same.
My aim is to design a movie reservation system. A user could click on one or more empty seats for a movie schedule to reserve them. But he needs to make a payment before 15mins is up, otherwise the reserved seats would have to be automatically given up for other users.
I have the following pseudo MySQL :
Table Movie:
id int primary key,
name varchar,
.....
Table MovieSched:
movie_id foreign key refers to Movie,
sched_id int primary key,
showtime datetime, // date and time of schedule
count_signup int, // number of sign ups
max_size int // max number of seats
Table MovieSchedSignUp:
sched_id foreign key refers to MovieSched,
user_id foreign key refers to User,
signup datetime // datetime of signup
Every movie schedule has a max_size of users who can sign up. To register a user, I insert a row in MovieSchedSignUp with the current date and time.
A few constraints naturally arise from the requirements:
Due to possible inconsistency between the interface and database, I need to inform a user A when there are not enough seats available when A tries to reserve seats. (for e.g., another user B could have bought all the seats right before A.)
I need to atomically insert a row in MovieSchedSignUp while ensuring the schedule is not "overbooked" (count_signup <= max_size) as well as updating count_signup at the same time.
I need to ensure payment is made within 15mins, otherwise the reserved seats have to be freed.
My thoughts are:
Have extra columns in MovieSchedSignUp to keep track of when payment is made.
Use a transaction, but how do I return information about whether there are enough seats or not?
Have a batch job running in the background to delete the "expired" rows in MovieSchedSignUp.
What is the most efficient way to go about doing this? Any other thoughts? Don't really want to use a batch job, but is there any other way out?

I think in this situation you are going to have to use a transaction.
Start the transaction
Insert the records to be added to a temp table
Do a join between the temp table, MovieSched and MovieSchedSignUp to
check the number of records (combined temp and MovieSchedSignUp) isn't greater than max size.
If OK then do the insert
If OK them commit the transaction, if not then roll back the
transaction.

Related

How to maintain multiple branches for a primary key (col1) and a json datatype column

I have a design question where I know that JSON is the best option but still facing issues with implementation.
Requirement:
I need to store business entity information. Attributes are (registration_NO (primary key), Address, phone number (multiple phone numbers), directors (multiple people) etc.
It is due to the one-to-many between registration_number and (phone number, and directors), I decided to go with jsonb datatype.
there are 2 conditions.
phone number, directors may be added, removed etc.
any new changes to the records need approval. Until approved, the old values will be displayed.
Problems I am facing:
say for example:
current record: Regno: directors, record_status (did not show phone number on purpose)
100: {John, Joe}, current; ok to display
when I add a new director, this entry must be a new branch of the registration# Primary key with status as "not yet approved" and therefore should not show up in queries.
100: {john, joe, jane}, updated; not yet approved.
however, when I update the row, the old value of directors is getting overwritten.
When I insert with status as "update; not yet approved", then it inserts a duplicate record for the registration#.
Ideally, I would like to have 2 branches for registration# 100 ; one approved to show, and one not approved to show.
How should I manage this? Any help is appreciated.
Rule of thumb: If your data has a predictable structure, you probably don't want to use a JSON column.
I would implement this with three tables. One table for the business entity, one for the phone numbers, and one for the directors. Something like this:
CREATE TABLE business_entity (
registration_no uuid,
address text,
PRIMARY KEY(registration_no)
);
CREATE TYPE status AS ENUM ('added', 'deleted');
CREATE TABLE business_entity_phone_number (
registration_no uuid,
phone_number text,
status status,
CONSTRAINT fk_business_entity_phone_number
FOREIGN KEY(registration_no) REFERENCES business_entity(registration_no)
);
CREATE TABLE business_entity_director (
registration_no uuid,
director text,
status status,
CONSTRAINT fk_business_entity_director
FOREIGN KEY(registration_no) REFERENCES business_entity(registration_no)
);
The status columns are there to track changes. So if a new phone number is added, we mark that row as "added" until it's approved, and if a row is deleted we leave it in place but mark it as "deleted" until it's approved.
Then, in order to query our business entities, we need only leave out "added" rows:
SELECT
be.registration_no,
address,
(
SELECT ARRAY_AGG(phone_number)
FROM business_entity_phone_number bepn
WHERE be.registration_no = bepn.registration_no
AND COALESCE(bepn.status, 'deleted') != 'added'
) as phone_numbers,
(
SELECT ARRAY_AGG(director)
FROM business_entity_director bed
WHERE be.registration_no = bed.registration_no
AND COALESCE(bed.status, 'deleted') != 'added'
) as directors
FROM business_entity be
Things this solution does not fully deal with:
Tracking changes to other fields in business_entity (it wasn't clear from the question if this is needed)
Updates to phone numbers/directors (or is adding/deleting enough?)
What happens when two users try to make conflicting changes?

Database design: Value(s) per user per day

I'm setting up a system where for every user (1000+), I want to add a set of values every single day.
Hypotetically:
A system where I can log when Alice and Bob woke up and what they had for dinner on the August 1st 2019 or 2024.
Any suggestions on how to best structure the database tables?
A person table with a primary person ID?
rows: n
A date table with a primary date ID?
rows: m
And a personDate table the person ID and date ID as foreign keys?
rows n x m
I don't think u need a date table unless u want to use it to make specific queries easier. Such as left join against the date to see what days you are missing events. Nevertheless, I would stick to the DATE or DATETIME as the field and avoid making a separate surrogate foreign key. It won't save any space and will potentially perform worse and will be more difficult to use for the developer.
This seems simple and fine to me. I wouldn't worry too much about the performance based upon the number of elements alone. You can insert a billion records with no problem and that implies a very large site.
Just don't insert records if the event didn't happen. In other words you want your database to grow in relation to the real usage. Avoid growth based upon phantom events and you should be okay.
person
person_id
action
action_id
personAction
person_id
action_id
action_datetime

MySQL constrain transaction for entity must finish before another can begin

I have a table for guests, each guest with a unique name.
I have a table for guest_transactions with guest_id, status_id, arrived_time, left_time.
And a status table with a name column, populated with values (here, leaving, left).
I want to record guests as they come and go, but I'd like to have a constraint which prevents a guest from arriving twice before leaving. Is there a way to do this?

vb.net how can i monitor logged in user task such as add, delete, update data in programme

I am creating an application in vb.net in which many users can add, update, and modify data stored in sql, but one user at a time. Users have to login to the application and then they can start their work. I want to know how I can monitor their work after they log out, like which user updated the record and at which time. Please help me with the logic and how I can make this application for monitor user task.
I already created the database in mysql in which I can store user log in and log out time now I want to store their work.
For a very basic solution, create a new table that's used exclusively for logging. Each action creates an entry (row) in that table that links their user account with a description of the action.
CREATE TABLE UserActivity
(
ActivityId INT NOT AUTO_INCREMENT PRIMARY KEY,
UserId INT NOT NULL,
Message VARCHAR(255),
Timestamp TIMESTAMP
);
If you want more detail, you could create the table to accept foreign keys to the actual entries in the table(s) that was/were changed. But I would start simple with a VARCHAR concise description, e.g.
INSERT INTO UserActivity (UserId, Message)
VALUES (123, 'Updated user 456');
If you're not looking for a complete history and are just looking for who last touched it, you can add two columns to each table: LastUpdated & LastUser, then update those two columns when anything is altered. (As #MarkHall suggested in a comment)
ALTER TABLE mytable
ADD COLUMN last_updated TIMESTAMP
ADD COLUMN last_user INT;

How to design a message/comment table in MySQL?

I am designing a message/comment table in MySQL for social networking site. I have a messaging system where participating two users (only two and not more than that) will have single/unique thread. So, whenever a user is messaging another user then it will check whether both user had unique thread IF NOT then it will create unique thread for both user.
create table comment_threads (
thread_id int (PK),
user_id_1 int,
user_id_2 int,
created datetime
);
create table comments (
comment_id int (PK),
thread_id int (FK),
comment text,
created datetime
);
Whenever a user messages another user each time then I have to check whether both of the participating user had previous thread so i have to query the database for that (QUERY 1). And then again if there wasn't any thread to create a thread in comment_thread (QUERY 2). Then again to post comment in comment table (QUERY 3). So I have to query two or three times for messaging.
Questions:
Is the above tables correct way of solving my problem or it needs some correction?
Is there any other better way to do it?
You don't really need to have 2 tables.. 1 table should be fine:
create table comments (
comment_id int (PK),
parent_id int,
user_id_1 int,
user_id_2 int,
comment text,
created datetime
);
For a new thread, set the parent_id to 0. For future comments, you can set the parent_id to the ID of first comment.
This way, you can also do multi-level threaded conversations, and it makes it easy to do stuff like 'comments I've posted'.
As per Itay's answer, you should use some caching mechanisms to improve performance.
You can't know which user left which message
When you instantiate the message system with a thread, cache the two users ids and thread id, no need to run to DB for each submit (this is not that simple, but rather a direction for you, you will need some failsafes mechanisems)
I would buffer in memory the thread and submit to DB only at a later time (or just use a memory table)
since this is a two users only, one thread only system, you can de-normalize and do the entire thread in one record inside a huge text field where you concatenate the latest entry to the end. Again, this is just a direction and not the complete solution.