How to LOCK a row in MySQL? - mysql

I'm working on a CRM desktop application which is going to be used by more than one agent at a time, and all agents will go through the same list of customers. What I need to do here is to avoid conflicts between agents, so once an agent selects a customer from the list, others shouldn't be able to see that row anymore, or in another words they shouldn't be able to select that customer row until the first agent is done ! The simplest way that comes in mind wich may sound stupid is to add two fields LOCK(BIT), LOCK_EXPIRY(DATETIME) and manage that. I don't know But I think there should be another way to lock a row for particular session. I searched on Google and I found two InnoDB locking methods but I'm not sure if those can help me here in this case.

I suggest you add the two fields you described, except replace LOCK(BIT) with LOCKED_BY(AGENT_ID). Otherwise if the agent that has locked the list of customers refreshes his/her page, the locked rows may disappear until the lock expires.

I think you can use GET_LOCK() function with MySQL:
http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_get-lock

Related

How to enable users only to view certain rows in a table

I currently have two tables. One is accounts and one is tbl_units_info. My boss wants me to make it so that accounts are restricted from reading certain rows in a table. Frankly, I think my boss has no idea what he is talking about, but I'm hoping someone here can prove me wrong.
For example, accountname krikara can only view the entries of the tbl_units_info table where the TBID column is 0909.
Is this even possible? To make krikara only able to view the rows in that table where column TBID = 0909?
It can not be implemented plainly on DBMS level since SELECT privilege has table level. You can not restrict rows reading. And this is good, I think - because data could be changed, so in general there is no solid condition for rows restriction (and, therefore, there could not be valid implementation for that on DBMS level).
You can, however, use VIEW - but it is a middlepoint, not common solution (I still not think it will help with tracking rows changes, but may be I'm wrong due to your application logic)
You can try to implement it in your application, but it still has problem I've described above: in table, data is changing. You'll probably have troubles with tracking all changes. I think you can separate your rows on two (several) tables and then build your permissions model. But - if some basically similar entities must have different permissions - probably you should reconsider application security model?
You could solve it by giving accounts just the reading rights to a view instead of the whole table.
CREATE VIEW `tbl_units_info_krikara` AS
SELECT * FROM `tbl_units_ino` WHERE `TBID`='0909';
And then assign the respective rights to your user.
MySQL CREATE VIEW documentation

How to synchronize table updates

I've single database table containing some financial information. Multiple users may be viewing and updating at the same time from a web form on their computers.
What I want is that anyone who does an update must be doing based on latest table contents. I mean two people may click update at the same time. Say first person's update is successful. Now the second person's update is based on stale information and did not get chance to see the latest update from the first person.
How to avoid such situation?
you have to set the isolation level of your database server to REPEATABLE READ at least. When it's used, the dirty reads and nonrepeatable reads cannot occur. It means that locks will be placed on all data that is used in a query, and another transactions cannot update the data.

Proper way to store requests in Mysql (or any) database

What is the "proper" (most normalized?) way to store requests in the database? For example, a user submits an article. This article must be reviewed and approved before it is posted to the site.
Which is the more proper way:
A) store it in in the Articles table with an "Approved" field which is either a 0, 1, 2 (denied, approved, pending)
OR
B) Have an ArticleRequests table which has the same fields as Articles, and upon approval, move the row data from ArticleRequests to Articles.
Thanks!
Since every article is going to have an approval status, and each time an article is requested you're very likely going to need to know that status - keep it inline with the table.
Do consider calling the field ApprovalStatus, though. You may want to add a related table to contain each of the statuses unless they aren't going to change very often (or ever).
EDIT: Reasons to keep fields in related tables are:
If the related field is not always applicable, or may frequently be null.
If the related field is only needed in rare scenarios and is better described by using a foreign key into a related table of associated attributes.
In your case those above reasons don't apply.
Definitely do 'A'.
If you do B, you'll be creating a new table with the same fields as the other one and that means you're doing something wrong. You're repeating yourself.
I think it's better to store data in main table with specific status. Because it's not necessary to move data between tables if this one is approved and the article will appear on site at the same time. If you don't want to store disapproved articles you should create cron script with will remove unnecessary data or move them to archive table. In this case you will have less loading of your db because you can adjust proper time for removing old articles for example at night.
Regarding problem using approval status in each query: If you are planning to have very popular site with high-load for searching or making list of article you will use standalone server like sphinx or solr(mysql is not good solution for this purposes) and you will put data to these ones with status='Approved'. Using delta indexing helps you to keep your data up-to-date.

What kind of locking/transaction isolation level is appropriate for this situation?

Let's say I have a Student and a School table. One operation that I am performing is this:
Delete all Students that belong to a School
Modify the School itself (maybe change the name or some other field)
Add back a bunch of students
I am not concerned about this situation: Two people edit the School/Students at the same time. One submits their changes. Shortly after, someone else submits their changes. This won't be a problem because, in the second user's case, the application will notice that they are attempting to overwrite a new revision.
I am concerned about this: Someone opens the editor for the Schools/Students (which involves reading from the tables) while at the same time a transaction that is modifying them is running.
So basically, a read should not be able to run while a transaction is modifying the tables. Additionally, a write shouldn't be able to occur at the same time either.
Only in serializable isolation level MySQL won't allow you to read the rows that are being modified by another transaction. In any lower isolation level, you will see the rows in the state they were before the transaction, that modifies them, have been started. Of course, in READ_UNCOMITTED, the rows will be seen as deleted / modified, although transaction hasn't been completed.
If you use select for update,
You can use locking of tables to prevent this. Check this for more info on lock tables
EDIT
Have a look at this how to lock some row as they don't be selected in other transaction . Think a similar method can be applied for tables also

MySQL - Saving and loading

I'm currently working on a game, and just a while ago i started getting start on loading and saving.
I've been thinking, but i really can't decide, since I'm not sure which would be more efficient.
My first option:
When a user registers, only the one record is inserted (into 'characters' table). When the user tries to login, and after he/she has done so successfully, the server will try loading all information from the user (which is separate across multiple tables, and combines via mysql 'LEFT JOIN'), it'll run though all the information it has and apply them to the entity instance, if it runs into a NULL (which means the information isn't in the database yet) it'll automatically use a default value.
At saving, it'll insert or update, so that any defaults that have been generated at loading will be saved now.
My second option:
Simply insert all the required rows at registration (rows are inserted when from website when the registration is finished).
Downsides to first option: useless checks if the user has logged in once already, since all the tables will be generated after first login.
Upsides to first option: if any records from tables are deleted, it would insert default data instead of kicking player off saying it's character information is damaged/lost.
Downsides to second option: it could waste a bit of memory, since all tables are inserted at registration, and there could be spamming bots, and people who don't even manage to get online.
Upsides to first option: We don't have to check for anything in the server.
I also noted that the first option may screw up any search systems (via admincp, if we try looking a specific users).
I would go with the second option, add default rows to your user account, and flag the main user table as incomplete. This will maintain data integrity across your database, whereas every user record is complete in it's entirety. If you need to remove the record, you can simply add a cascading delete script to clean house.
Also, I wouldn't develop your data schema based off of malacious bots creating accounts. If you are concerned about the integrity of your user accounts, add some sort of data validation into your solution or an automated clean-house script to clear out incomplete accounts once the meet a certain criteria, i.e. the date created meeting a certain threshold.
You mention that there's multiple tables of data for each user, with some that can have a default value if none exist in the table. I'm guessing this is set up something like a main "characters" table, with username, password, and email, and a separate table for something like "favorite shortcuts around the site", and if they haven't specified personal preferences, it defaults to a basic list of "profile, games list, games by category" etc.
Then the question becomes when registering, should an explicit copy of the favorite shortcuts default be added for that user, or have the null value default to a default list?
I'd suggest that it depends on the nature of the auxiliary data tables; specifically the default value for those tables. How often would the defaults change? If the default changes often, a setup like your first option would result in users with only a 'basic' entry would frequently get new auxiliary data, while those that did specify their own entries would keep their preferences. Using your second option, if the default changed, in order to keep users updated, a search/replace would have to be done to change entries that were the old default to the new default.
The other suggestion is to take another look at your database structure. You don't mention that your current table layout is set in stone; is there a way to not have all the LEFT JOIN tables, and have just one 'characters' table?