Tip

MySQL tutorial: Best practices for securing tables, triggers and privileges

Although there is no way to limit table access on a per-use basis in MySQL, you can use stored procedures to limit user access to data. This is one of the many security workarounds that Scott Noyes, SearchEnterpriseLinux.com's MySQL expert, suggests, in addition to explaining the differences between user and local variables and preventing privilege pass-alongs by users.

    Requires Free Membership to View

More on MySQL:
Mastering MySQL: Ten essential tips

Getting started with MySQL 

Noyes is a MySQL Core-, Developer- and DBA-certified engineer. He is also the senior Web applications developer for Bookit.com.

How can you prevent users from passing on privileges granted to them on certain tables?

Scott Noyes: When issuing the GRANT statement, you have the option of appending WITH GRANT OPTION to the end. If that option is set, then users will be allowed to issue their own GRANT statements to other users. If you do not include that option, any attempt to issue a grant statement will be met with an access denied error.

Is there a way to limit access a table via a per-use basis in MySQL using the GRANT statement?

Noyes: The GRANT statement provides the following access limitations on a user:

  • The number of queries per hour
  • The number of updates per hour
  • The number of connections to the server per hour
  • The number of simultaneous connections to the server

There is no built-in method to limit the number of times a user may access a particular table outside of the per hour limits.

You can use stored procedures to limit user access to data. Construct a stored procedure that logs user access to the table (referencing the CURRENT_USER() function as needed), and exits early if the table has already been accessed. Give your users access only to the stored procedure, and not directly to the table itself.

What is the difference between user variables and local variables?

Noyes: Local variables refer to variables declared within a stored routine. Their scope is limited to the BEGIN and END block in which they are declared.

User variables are named with the @ symbol, and have global scope within the connection (you can set them inside a stored procedure, and still access them after the procedure has finished, for example).

How do you create a trigger for my USERS table that means if one user is removed, that user is also taken out of the USERS_DIR table?

Noyes: If you use the InnoDB storage engine, there is no need for a trigger. You can achieve the same effect using a foreign key with an appropriate cascading action:

ALTER TABLE users_dir ADD FOREIGN KEY (userId) REFERENCES users (userId) ON DELETE CASCADE;

If you use MyISAM or one of the other engines that does not yet enforce foreign key constraints, you can use a trigger:

CREATE TRIGGER users_AD AFTER DELETE ON users FOR EACH ROW DELETE FROM
users_dir WHERE userId = OLD.userId;

Note that the foreign key is defined on the users_dir table, but the trigger is defined on the users table.

The examples shown here for both foreign keys and triggers only address behavior if the user is deleted. You will need to decide what action to take if the user's id is updated to a different value instead.

Where should you put a NOT EXIST subquery, named as a column, in a statement with several joins ahead of it?

Noyes: Aliases defined in the select list, whether aliases of simple columns, results of expressions or subqueries, should not appear in the where clause. To use a subquery in the where clause, you should redefine it.

Using NOT EXISTS is one way to find rows which appear in one table but do not appear in another:

SELECT
  t1.*
FROM
  t1
WHERE
  NOT EXISTS (SELECT * FROM t2 WHERE t1.id = t2.id)

Such correlated subqueries can often be rewritten as joins:

SELECT
  t1.*
FROM
  t1
  LEFT JOIN t2 ON (t1.id = t2.id)
WHERE
  t2.id IS NULL;

Test both approaches on your data. A different index or table size can make one approach faster than the other in different situations. Of course, if you're on a hosted server that still hasn't upgrade from 3.23 or 4.0, subqueries aren't available anyway, so you'll have to use the join form.

This was first published in June 2007

There are Comments. Add yours.

 
TIP: Want to include a code block in your comment? Use <pre> or <code> tags around the desired text. Ex: <code>insert code</code>

REGISTER or login:

Forgot Password?
By submitting you agree to receive email from TechTarget and its partners. If you reside outside of the United States, you consent to having your personal data transferred to and processed in the United States. Privacy
Sort by: OldestNewest

Forgot Password?

No problem! Submit your e-mail address below. We'll send you an email containing your password.

Your password has been sent to:

Disclaimer: Our Tips Exchange is a forum for you to share technical advice and expertise with your peers and to learn from other enterprise IT professionals. TechTarget provides the infrastructure to facilitate this sharing of information. However, we cannot guarantee the accuracy or validity of the material submitted. You agree that your use of the Ask The Expert services and your reliance on any questions, answers, information or other materials received through this Web site is at your own risk.