I caution against treating the Model as simply a data access layer. That's oversimplifying, and it results in you putting too much code into the Controller Layer. It's better if you put more of that code in the Model, and make database persistence only a part of the Model's internal code. I like to think of MVC like this:
- Controller: handle input, determine which Model and which View to instantiate
- View: presentation of application data
- Model: all other logic for the application, including but not limited to DAL
This is basically the Page Controller pattern.
Another way to think about it is this: suppose you had to port your web app to another platform, such as a command-line app or a desktop GUI app. What parts of the application logic should you reuse? The Controller and View would change as you port your app to another platform, because the implementation of both input and output would need to change. The code that doesn't need to change should be implemented in your Model.
If you've done the separation of concerns right, then the Model, View, and Controller would be minimally coupled, and you could change the implementation of one without affecting the others too much. If you change the Model and you find yourself rewriting a lot of code in the Controller or the View, you probably haven't separated these layers adequately. And vice versa.
Read about Martin Fowler's Anemic Domain Model antipattern or Domain Driven Design Quickly to get some other perspectives.
Also see my blog from 2008 that I wrote in response to people decrying the Active Record pattern. It got some good comments and discussion.