In N-Tier applications, it is a good idea to separate your middle tier from your from the details or inner working of your data repository(s). In some projects this can be overkill.
This abstraction allows you to switch out RDMS or connect to multiple RDMS's without rewriting the business layer logic. Your code will also benefit from the modularity.
One way to achieve this is to encapsulate all your database tables with CRUD's (ORM mappers make this easy). In a since, these classes would become your data layer.
For example, At the highest level of your data layer, you might have a function that returns a list of users by userid, here user is a defined class that has matching properties to your data fields. So instead of returning some system data table object you are returning a list of your defined user objects.
Next, in your business layer, you plug into or are giving a data access class that you can get a list of users from (see dependency injection). You do not need to know, nor do you care, where the data came from. The list of users could have come from MySQL, a flat file, or a remote web service. This is why separation can be a good thing.
Some of the drawbacks to this approach would be having to rely on a third party ORM mappers (they make development faster), the need for translation classes for cross boundary communication, more planning involved for even the smallest of tweaks. However, the last point is less likely if you have CRUDS for every entity. The tweaks would only be needs when you change the attributes of the underlying data.
Edit: I forgot to mention that the Get/Update/Insert/Delete functions of your user repository would normally be accessible via an api tucked into a remote web service or something similar.