The observed behaviour will appear in any expression whose symbolic head has the attribute `Flat`.

Under normal circumstances, with no attributes in play, we see the usual expected behaviour:

    MatchQ[f[1], f[1]]            (* True *)
    MatchQ[f[1], f[a_]]           (* True *)
    MatchQ[f[1], f[f[1]]]         (* False *)
    MatchQ[f[1], f[f[a_]]]        (* False *)
    MatchQ[f[1, 2, 3], f[a_]]     (* False *)

But when we introduce the `Flat` attribute, our normal intuition no longer holds:

    SetAttributes[g, Flat]

    MatchQ[g[1], g[1]]            (* True*)
    MatchQ[g[1], g[a_]]           (* True*)
    MatchQ[g[1], g[g[1]]]         (* True*)
    MatchQ[g[1], g[g[a_]]]        (* True *)
    MatchQ[g[1, 2, 3], g[a_]]     (* True *)

**What is happening?**

The purpose of `Flat` is to flatten out any nested expressions.  That is, `g[g[1, 2, 3]]` is to be treated as equivalent to `g[1, 2, 3]`.  The key point is that this equivalence works both ways.  So when we ask whether `g[1, 2, 3]` matches the pattern `g[a_]`, then this is equivalent to asking whether `g[g[1, 2, 3]]` matches `g[a_]`.  Which of course it does.  That is why the `MatchQ` expression in the question returns `True`.  As does `MatchQ[g[g[g[g[g[1, 2, 3]]]]], g[a_]]`

**Can we turn it off?**

A simple way to perform the exact match requested by the question is to temporarily remove the `Flat` attribute from `Times`.  `Block` will strip `Times` of all of its attributes:

    Block[{Times}
    , MatchQ[
        HoldComplete[Times[3, 2, 2]]
      , HoldComplete[Times[a_]]
      ]
    ]
    (* False *)

If, for some reason, the application is such that we wish to retain the other attributes of `Times`, we can use ``Internal`InheritedBlock``:

    Attributes[Times]
    (* {Flat, Listable, NumericFunction, OneIdentity, Orderless, Protected} *)

    Internal`InheritedBlock[{Times}
    , Unprotect[Times]
    ; ClearAttributes[Times, Flat]
    ; Protect[Times]
    ; { MatchQ[
          HoldComplete[Times[3, 2, 2]]
        , HoldComplete[Times[a_]]
        ]
      , Attributes[Times]
      }
    ]
    (* {False, {Listable, NumericFunction, OneIdentity, Orderless, Protected}} *)