Database access control (DAC) is the set of policies and mechanisms that decide who can connect to a database, what they can do, and for how long. Most implementations stop at the connection — and the connection is not where the damage happens. The statement is.
Authentication is a one-time gate at connection. Authorization fires on every statement — and this is where most real-world DAC fails. A user with a valid connection and a broadly-scoped role can do anything the role allows, with no further check on the actual SQL.
Note: "DAC" is also used in security literature for discretionary access control, the access-control model contrasted with MAC and RBAC. This article uses DAC for database access control throughout.
Machine, human, and agentic access are three different problems
The biggest source of DAC failure is applying one playbook to fundamentally different workloads. There are three.
Machine to database. Application servers, ETL pipelines, scheduled jobs. Predictable, repeated, scoped to known tables. Machine accounts get narrow, permanent permissions deployed alongside the application. Their access shape changes at the speed of releases.
Human to database. Schema changes, data corrections, ad-hoc queries, incident response, admin operations. Unpredictable, varied, and where most production incidents originate. Human accounts need broad capabilities — but only at specific moments, only for a stated reason, and always with a per-action audit trail. Their access shape changes at the speed of on-call rotations, team movements, and outages.
Agent to database. Coding assistants, MCP-connected copilots. Intent comes from a natural-language prompt; the SQL is generated on the fly. Operates at machine speed but produces human-shaped queries — novel, varied, occasionally destructive. Acting on behalf of a person, which means the audit record needs two identities: the agent's service account and the requesting principal. Access shape changes at the speed of prompts.
All three share the principles (least privilege, named identity, full audit) and diverge sharply on implementation. The generic DAC advice — set up roles, grant SELECT on the tables they need — works cleanly for machines. For humans, it produces either standing privileges nobody can justify or developer toil that drives teams to share an admin account. For agents, it produces the worst of both: a service account with machine-shaped permanence but human-shaped unpredictability — and no record of which prompt produced which DELETE.
A working DAC system answers four questions
For every active grant — machine, human, or agent:
- Who is connecting? A named individual, workload identity, or agent — and for agents, the requesting principal must be recorded alongside the service account.
- What can they do? Read, write, alter schema, grant permissions to others.
- Where can they do it? Which databases, schemas, tables, columns.
- How long does the access last? Permanent, time-boxed, or on-demand.
If you cannot answer all four for an active grant, that grant is a gap. The fourth question is the one most often missing: standing access accumulates because nobody set a clock on it, and "temporary" grants rarely stay temporary.
Where connection-time control stops short
Privileged Access Management (PAM), VPNs, and bastion hosts all gate the connection. That is necessary and not sufficient. Two failure modes survive a clean connection gate:
- Untracked actions inside an approved session. A user with a valid two-hour grant runs 200 queries; only one of them drops a table. Session-level logs prove the user was connected; they do not answer "which statement, at what time, with what result". Compliance auditors ask the second question.
- Sensitive data flowing through approved channels. A role-based grant says the user can
SELECTfromcustomers. It does not say whethercustomers.tax_idshould be masked for this user. Column-level policy and dynamic masking live outsideGRANT/REVOKEand have to be enforced at statement time.
Connection-time DAC misreads where the risk lives. The unit of risk is not the session — it is the statement. Every statement is a control point.
Compliance requires the statement-level answer
Every major compliance framework requires database-level access controls — and the audit findings concentrate on the same three gaps regardless of framework:
| Framework | Access control requirement | Audit trail required? |
|---|---|---|
| SOC 2 (CC6.1, CC6.3) | Least privilege, regular access reviews | Yes |
| HIPAA (§164.312) | Unique user IDs, emergency access procedures | Yes |
| GDPR | Access limited to purpose of processing | Yes |
| PCI DSS (Req 7, 8) | Role-based access, no shared accounts | Yes |
| SOX | Separation of duties, change audit trails | Yes |
| ISO 27001 (A.9) | Formal access provisioning and de-provisioning | Yes |
What teams fail on is rarely the policy text. It is shared service accounts that hide who actually ran the query, standing privileges nobody can justify, and audit trails that record sessions but not statements.
The Bytebase shape
Bytebase treats database access control as a statement-level workflow problem, not a connection-level RBAC problem. Identity, permissions, masking, approval, and audit all act on the same surface: the SQL a user is about to run. Machine workloads connect through the same identity model with first-class service accounts. Human workloads route through approval chains, time-boxed grants, and a per-statement audit log. AI agents operate through service accounts that inherit the same statement-level review, masking, and audit as humans — and the requesting person is bound to every action the agent takes, so the audit trail answers "which prompt produced this query", not just "which service account ran it."
For the principles that translate this shape into day-to-day practice — least privilege, separation of duties, just-in-time access, RBAC, and the common mistakes that fail audits — see Database Access Control Best Practices.