hook_node_access() is a standalone hook and has nothing to do with the node_access table.
hook_node_access_records() and hook_node_grants() go together and are different to hook_node_access(). These hooks use the node_access table.
Basically, the node_access table stores all the access grants for nodes.
These grants can then be queried and joined to other queries to check the access rules for a node.
hook_node_access_records() is invoked when writing access rules to the node_access table and hook_node_grants() is invoked when reading them out again.
To give you a better idea of how the hooks work, look at the code where they get invoked from.
For hook_node_access_records() this is node_access_acquire_grants().
It invokes the hook and then writes all the returned grants to the node_access table.
hook_node_grants() is called from a few places, but generally via the node_access_grants() function, which is called from a few places. Take a look at the node_access() function as an example.
It queries the node_access table, adding to the query conditions any access grants returned by modules that implement hook_node_access_grants(). Note that grants are also alterable via hook_node_grants_alter().
While you are looking at the node_access() function you can also see how hook_node_access() is called and you'll see how it is different and why it's not as flexible a solution to access control.
In case you haven't seen it, this is a good article on the topic: http://www.phase2technology.com/blog/drupal-7-node-access-grants-locks-and-keys/